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


win.gevent = {
    handle : function(event){
        var all, handlers;
        //包装event
        event = arguments[0] = gevent.fix( event || window.event );
        event.currentTarget = this;
        //这里的........
        var namespaces = event.type.split(".");
        event.type = namespaces.shift();
        all = !namespaces.length;
        var namespace = RegExp("(^|\\.)" + namespaces.slice().sort().join(".*\\.") + "(\\.|$)");
        //取这个元素的该行为 的 事件列表
        handlers = (data(this, "events") || {} )[event.type];           
        //遍历这个事件列表 执行该执行的东西
        for ( var j in handlers ) {
            var handler = handlers[j];
            if ( all || namespace.test(handler.type) ) {
                // Pass in a reference to the handler function itself
                // So that we can later remove it
                // jq上的注释是是这么写的 把event的handler 引用这个事件 方便之后移除
                // 但是在remove里面 并没有用到event的handler  不知道这里到底有什么用  且有多个事件的时候这个事件被取代
                event.handler = handler;
                //执行事件 并且是用元素调用的事件 可以吧事件里面的this执行元素 ret为函数的返回值
                var ret = handler.apply(this, arguments);
                //如果有返回值  且返回值是false 执行阻止事件冒泡 阻止执行事件默认行为                       
                if( ret !== undefined ){
                    event.result = ret;
                    if ( ret === false ) {
                        event.preventDefault();
                        event.stopPropagation();
                    }
                }   
            }               
        }
    },
    props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),       
    fix : function(event){
        //new setEvent会给event给以个expando属性 如果有中个属性 说明已经生成了event了 不需要在次对event进行包装
        if ( event[expando] )
            return event;
        //保留一个原始的event
        // new一个新的event 这个与原始的event是不同的
        var originalEvent = event;
        event = new setEvent( originalEvent );
        //获得原始event的属性值  有哪些属性值 见 this.props
        for ( var i = this.props.length, prop; i; ){
            prop = this.props[ --i ];
            event[ prop ] = originalEvent[ prop ];
        }
        //将目标元素同一成event.target
        if ( !event.target )
            event.target = event.srcElement || document; // Fixes #1925 where srcElement might not be defined either
        //如果发现是文本节点 取他的父节点
        if ( event.target.nodeType == 3 )
            event.target = event.target.parentNode;
       
        if ( !event.relatedTarget && event.fromElement )
            event.relatedTarget = event.fromElement == event.target ? event.toElement : event.fromElement;                           
        return event;
    }       
}
win.setEvent = function(src){
    // Allow instantiation without the 'new' keyword
    // Event object
    if( src && src.type ){
        this.originalEvent = src;
        this.type = src.type;
    // Event type
    }else
        this.type = src;
    // timeStamp is buggy for some events on Firefox(#3843)
    // So we won't rely on the native value
    this.timeStamp = now();
    // Mark it as fixed
    this[expando] = true;
}
function returnFalse(){
    return false;
}
function returnTrue(){
 return true;
}
setEvent.prototype = {
 preventDefault: function() {   
     var e = this.originalEvent;
     if( !e )
         return;
     // if preventDefault exists run it on the original event
     if (e.preventDefault)
         e.preventDefault();
     // otherwise set the returnValue property of the original event to false (IE)
     e.returnValue = false;
 },
 stopPropagation: function() {   
     var e = this.originalEvent;
     if( !e )
         return;
     // if stopPropagation exists run it on the original event
     if (e.stopPropagation)
         e.stopPropagation();
     // otherwise set the cancelBubble property of the original event to true (IE)
     e.cancelBubble = true;
 },
 stopImmediatePropagation:function(){
     this.isImmediatePropagationStopped = returnTrue;
     this.stopPropagation();
 },
 isImmediatePropagationStopped: returnFalse
};   

一个完整的例子

复制代码 代码如下:

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

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