浅谈jQuery事件绑定原理(2)

win.each = function( object, callback, args ) { 
    var name, i = 0, length = object.length; 
    if ( args ) { 
        if ( length === undefined ) { 
            for ( name in object ) 
                if ( callback.apply( object[ name ], args ) === false ) 
                    break; 
        } else 
            for ( ; i < length; ) 
                if ( callback.apply( object[ i++ ], args ) === false ) 
                    break; 
    } else { 
        if ( length === undefined ) { 
            for ( name in object ) 
                if ( callback.call( object[ name ], name, object[ name ] ) === false ) 
                    break; 
        } else 
            for ( var value = object[0]; 
                i < length && callback.call( value, i, value ) !== false; value = object[++i] ){} 
    } 
    return object; 
}


 
接着实现添加事件

jq里面是在 jQuery.event里面的add方法
在add方法里面实现了一下一些功能
取元素的events,handle这2个data绑定的数据
events存放的是事件列表
格式如下
{
click: [{handler:function(){},type:"click",guid:'xx'}.......],
mouse:[......]
}
handle是执行的函数
(所有的执行函数都是一样的 他们遍历事件列表    执行对应的事件)
然后遍历types   因为可以绑定多个事件
回调函数也会给几个属性
假设回调函数是handler
handler.guid = gevent.guid++
handler.type =  name
name应该算一个特殊的命名  方便删除用的
比如
$('#xx')
.bind('click',function(){})
.bind('click.d',handler)
name就是d了
删除的时候可以只删除d那个事件  不删除上面的那个 click事件
 
最后是给元素绑定事件 但是执行的函数都是
function(){
 gevent.handle.apply(arguments.callee.elem, arguments);
});

复制代码 代码如下:


win.gevent = {
    guid : 1,
    add  : function (elem, types, handler){
        if ( elem.nodeType == 3 || elem.nodeType == 8 )
            return;
        if ( elem.setInterval && elem != window )
            elem = window;
        //给函数一个唯一标识的索引  方便后面删除该事件   
        if ( !handler.guid )
            handler.guid = this.guid++;
        //获得该元素的events handle 下的数据   
        var events = data(elem, "events") || data(elem, "events", {}),
            handle =data(elem, "handle") || data(elem, "handle", function(){
                //gevent.handle才是各种行为触发后会执行的函数
                gevent.handle.apply(arguments.callee.elem, arguments);
            });
        handle.elem = elem;
        //遍历事件名 因为可以是 click mouseover
        each(types.split(/\s+/), function(index, type) {
            var namespaces = type.split(".");
            //获得事件名
            type = namespaces.shift();
            //去掉点后面的东西 是个特殊的命名  在删除的时候可以指定删除他  如 click.d
            //用事件的type 记录住这个特殊的命名
            handler.type = namespaces.slice().sort().join(".");
            //获得该事件是否已经存在events 这个对象里面了
            var handlers = events[type];
            //如果不存在该事件 给元素绑定该事件               
            if (!handlers) {
                handlers = events[type] = {};
                if (elem.addEventListener)
                    elem.addEventListener(type, handle, false);
                else if (elem.attachEvent)
                    elem.attachEvent("on" + type, handle);                                       
            }
            //吧函数放到元素的该事件的列表里面
            handlers[handler.guid] = handler;                                       
        });
        elem = null;                                                   
    }
}


 
gevent.hander是绑定事件真正执行的函数
在gevent.hander里面也有取.特殊命名的地方  但是不知道做什么用的
hander里面先对event进行包装
包装见gevent. fix 和 setEvent
主要是对做一个原生event的一个copy  然后把不兼容的方法  都合成兼容的写法
然后取元素的events (事件列表)
然后遍历这个事件列表  判断type是不是事件列表的key 是的话就执行事件
在执行列表函数的时候会判断返回值
如果返回false  还可以组织事件冒泡 和 默认行为

复制代码 代码如下:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wgxdyz.html