//事件添加方法
function addEvent(element, type, handler) {
//保证每个不同的事件响应函数只有唯一一个id
if (!handler.$$guid) handler.$$guid = addEvent.guid++;
// 给element维护一个events属性,初始化为一个空对象。
// element.events的结构类似于 { "click": {...}, "dbclick": {...}, "change": {...} }
if (!element.events) element.events = {};
// 试图取出element.events中当前事件类型type对应的对象(这个对象更像数组),赋值给handlers
//如果element.events中没有当前事件类型type对应的对象则初始化
var handlers = element.events[type];
if (!handlers) {
handlers = element.events[type] = {};
// 如果这个element已经有了一个对应的事件的响应方法,例如已经有了onclick方法
// 就把element的onclick方法赋值给handlers的0元素,此时handlers的结构就是:
// { 0: function(e){...} },这也是为什么addEvent.guid初始化为1的原因,预留看为0的空间;
// 此时element.events的结构就是: { "click": { 0: function(e){...} }, /*省略其他事件类型*/ }
if (element["on" + type]) {
handlers[0] = element["on" + type];
}
}
// 把当前的事件handler存放到handlers中,handler.$$guid = addEvent.guid++; addEvent.guid = 1; 肯定是从1开始累加的
//因此,这是handlers的结构可能就是 { 0: function(e){...}, 1: function(){}, 2: function(){} 等等... }
handlers[handler.$$guid] = handler;
//下文定义了一个handleEvent(event)函数,将这个函数,绑定到element的type事件上作为事件入口。
//说明:在element进行click时,将会触发handleEvent函数,handleEvent函数将会查找element.events,并调用相应的函数。可以把handleEvent称为“主监听函数”
element["on" + type] = handleEvent;
};
//计数器
addEvent.guid = 1;
function removeEvent(element, type, handler) {
// delete the event handler from the hash table
if (element.events && element.events[type]) {
delete element.events[type][handler.$$guid];
}
};
function handleEvent(event) {
//兼容ie
event = event || window.event;
//this是响应事件的节点,这个接点上有events属性(在addEvent中添加的)
//获取节点对应事件响应函数列表
var handlers = this.events[event.type];
// 循环响应函数列表执行
for (var i in handlers) {
//保持正确的作用域,即this关键字
this.$$handleEvent = handlers[i];
this.$$handleEvent(event);
}
};
<input type="text" id="chua" onClick="f0();">
function f0(){...}
function f1(){...}
function f2(){...}
function f3(){...}
var dom = document.getElementById("chua");
addEvent(dom,"click",f1);
addEvent(dom,"change",f1);
addEvent(dom,"change",f2);
addEvent(dom,"click",f3);
addEvent(dom,"change",f3);
element: {
onclick: handleEvent(event), //click事件的主监听函数
onchage: handleEvent(event), //change事件的主监听函数
events: {
click:{//这是一个类数组
0: f0, //element已有的事件
1: f1, //下标1实际上就是f1.$$guid
3: f3 //下标3实际上就是f3.$$guid,需要注意的是每一个响应事件都有一个唯一的$$guid作为下标
...
},
change:{//这是一个类数组
1: f1,
2: f2,
3: f3
}
}
}
//保证每个不同的事件响应函数只有唯一一个id if (!handler.$$guid) handler.$$guid = addEvent.guid++;
handlers[handler.$$guid] = handler;
add: function( elem, types, handler, data, selector ) {
var tmp, events, t, handleObjIn,
special, eventHandle, handleObj,
handlers, type, namespaces, origType,
//获取elem节点对应的缓存数据
elemData = jQuery._data( elem );
//没有数据或文本/注释节点不能附加事件(但是允许附加普通对象)
if ( !elemData ) {
return;
}
//调用者能通过自定义数据替换handler
if ( handler.handler ) {
handleObjIn = handler;
handler = handleObjIn.handler;
selector = handleObjIn.selector;
}
//确保handler函数有唯一的ID,后续会用来查找/删除这个handler函数
if ( !handler.guid ) {
handler.guid = jQuery.guid++;
}
//如果是初次进入,初始化元素的事件结构和主事件响应入口
if ( !(events = elemData.events) ) {
events = elemData.events = {};
}
if ( !(eventHandle = elemData.handle) ) {
eventHandle = elemData.handle = function( e ) {
//当一个事件被调用后页面已经卸载,则放弃jQuery.event.trigger()的第二个事件,
return typeof jQuery !== core_strundefined && (!e || jQuery.event.triggered !== e.type) ?
jQuery.event.dispatch.apply( eventHandle.elem, arguments ) :
undefined;
};
//将elem作为handle函数的一个特征防止ie非本地事件引起的内存泄露
eventHandle.elem = elem;
}
//多个事件使用空格隔开的处理
//如jQuery(...).bind("mouseover mouseout", fn);
//core_rnotwhite = /\S+/g;匹配空白字符
types = ( types || "" ).match( core_rnotwhite ) || [""];
t = types.length;
while ( t-- ) {
//rtypenamespace = /^([^.]*)(?:\.(.+)|)$/;
//获取命名空间和原型事件
tmp = rtypenamespace.exec( types[t] ) || [];
type = origType = tmp[1];
namespaces = ( tmp[2] || "" ).split( "." ).sort();
//如果事件改变其类型,使用special事件处理器来处理更改后的事件类型
special = jQuery.event.special[ type ] || {};
//如果选择器已定义,确定special事件API类型,否则给他一个类型
type = ( selector ? special.delegateType : special.bindType ) || type;
//基于新设置的类型更新special
special = jQuery.event.special[ type ] || {};
// handleObj贯穿整个事件处理
handleObj = jQuery.extend({
type: type,
origType: origType,
data: data,
handler: handler,
guid: handler.guid,
selector: selector,
// For use in libraries implementing .is(). We use this for POS matching in `select`
//"needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" +
//whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
//用来判断亲密关系
needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
namespace: namespaces.join(".")
}, handleObjIn );
//初次使用时初始化事件处理器队列
if ( !(handlers = events[ type ]) ) {
handlers = events[ type ] = [];
handlers.delegateCount = 0;
//非自定义事件,如果special事件处理器返回false,则只能使用addEventListener/attachEvent
if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
//给元素绑定全局事件
if ( elem.addEventListener ) {
elem.addEventListener( type, eventHandle, false );
} else if ( elem.attachEvent ) {
elem.attachEvent( "on" + type, eventHandle );
}
}
}
//自定义事件绑定
if ( special.add ) {
special.add.call( elem, handleObj );
if ( !handleObj.handler.guid ) {
handleObj.handler.guid = handler.guid;
}
}
//将事件对象handleObj添加到元素的处理列表,代理计数递增
if ( selector ) {
handlers.splice( handlers.delegateCount++, 0, handleObj );
} else {
handlers.push( handleObj );
}
//跟踪那个事件曾经被使用过,用于事件优化
jQuery.event.global[ type ] = true;
}
//防止ie内存泄漏
elem = null;
}
<div id="#center"></div>
<script>
function dohander(){console.log("dohander")};
function dot(){console.log("dot");}
$(document).on("click",'#center',dohander)
.on("click",'#center',dot)
.on("click",dot);
</script>
elemData = jQuery._data( elem );
elemData = {
events: {
click: {//Array[3]
0: {
data: undefined/{...},
guid: 2, //处理函数的id
handler: function dohander(){…},
namespace: "",
needsContext: false,
origType: "click",
selector: "#center",//选择器,用来区分不同事件源
type: "click"
}
1: {
data: undefined/{...},
guid: 3,
handler: function dot(){…},
namespace: "",
needsContext: false,
origType: "click",
selector: "#center",
type: "click"
}
2: {
data: undefined,
guid: 3,
handler: function dot(){…},
namespace: "",
needsContext: false,
origType: "click",
selector: undefined,
type: "click"
}
delegateCount: 2,//委托事件数量,有selector的才是委托事件
length: 3
}
}
handle: function ( e ) {…}/*事件处理主入口*/{
elem: document//属于handle对象的特征
}
}
机械节能产品生产企业官网模板...
大气智能家居家具装修装饰类企业通用网站模板...
礼品公司网站模板
宽屏简约大气婚纱摄影影楼模板...
蓝白WAP手机综合医院类整站源码(独立后台)...苏ICP备2024110244号-2 苏公网安备32050702011978号 增值电信业务经营许可证编号:苏B2-20251499 | Copyright 2018 - 2025 源码网商城 (www.ymwmall.com) 版权所有