请提前阅读jQuery.Event的部分
测试代码1:
$("button").click(function(e){ alert(e instanceof jQuery.Event);//打印true表示是jQuery.Event对象 alert(e instanceof MouseEvent);//打印false表示不是js的Event对象 alert(e.originalEvent instanceof jQuery.Event);//打印false,表示originalEvent不是jQuery.Event对象 alert(e.originalEvent instanceof MouseEvent);//打印true,表示originalEvent是原生的MouseEvent对象 }); });
document.getElementById("btn1").onclick=function(e) { alert(e instanceof MouseEvent);//true alert(e.type);//click alert(typeof e.type);//string } //trigger函数里面调用代码: new jQuery.Event( type, typeof event === "object" && event ); //其中type是click字符串,请参照后面的jQuery.Event分析测试代码3:
$("button").click(function(e){ var eve=new jQuery.Event( "click", typeof e=== "object" && e ); console.log(eve.type);//click console.log(eve.originalEvent instanceof MouseEvent);//true console.log(eve instanceof jQuery.Event);//已经从JS的event对象转化为jQuery的Event对象了 });这种方式是从JS的事件对象来构造jQuery的事件对象!
测试代码4:
//每个jQuery.Event都有一个timeStamp属性,获取到timeStamp以后就能够通过new Date()构造一个时间,调用toLocalString就是本地时间了! $("div").click( function(event) { var datetime = new Date( event.timeStamp ).toLocaleString(); var html = '你于[' + datetime + "]点击了该元素"; html += '<br>( event.timeStamp = ' + event.timeStamp + ' )'; $(this).html( html ); } );
每一个jQuery.Event对象都有一个timestamp属性,通过该属性结合Date构造函数和toLocalString就可以获取本地时间!
测试代码5:
//这是给jQuery的event原型对象的属性:jQuery.Event.prototype function returnFalse() { return false; } function returnTrue() { return true; }测试代码6:
$("a").click(function(event){ console.log(event);//[object Object]对象 console.log(event instanceof jQuery.Event);//返回true,表示调用preventDefault的对象是jQuery.Event对象! console.log(event.originalEvent);//[object MouseEvent] console.log(event.type);//打印click console.log(event.timeStamp);//打印一连串字符串! console.log(event[jQuery.expando]);//打印true console.log(event.isDefaultPrevented);//打印function E(){return !1}也就是return false event.preventDefault(); });我们要知道每一个jQuery.Event对象都有一个jQuery.expando属性!在一般的DOM中该属性用于保存数据!
<p>段落文本内容 <input type="button" value="点击" /> </p>JS部分:
// 为所有p元素绑定click事件 $("p").click( function(event){ console.log("p-click"); } ); // 为所有button元素的click事件绑定第一个事件处理函数 $(":button").click( function(event){ console.log("button-click-1"); //可以从源码中看到isImmediatePropagationStopped函数定义 console.log( event.isImmediatePropagationStopped() ); // false event.stopImmediatePropagation(); console.log( event.isImmediatePropagationStopped() ); // true } ); // 为所有button元素的click事件绑定第二个事件处理函数 $(":button").click( function(event){ console.log("button-click-2"); } );因为第一个click事件中调用了stopImmediatePropagation,所以后面虽然该元素上还保存了其它的事件处理函数,但是并不会调用!如果把他换做stopPropagation那么后面的函数也会调用,因为后者只是会停止 冒泡!
测试代码8( jQuery.Event在源码中的几种调用方式):
(1)new jQuery.Event( type, typeof event === "object" && event ); //其中type有可能是click字符串。给event赋值type属性,同时让该jQuery.Event继承原来的event的所有属性! (2)type = hasOwn.call( event, "type" ) ? event.type : event;//jQuery的事件对象也有type属性 (3)event = new jQuery.Event( originalEvent );//给event赋值originalEvent,type,和isDefaultPrevented 等 (4)new jQuery.Event()测试代码9:
$("p").click( function(event){ var f1=event.isImmediatePropagationStopped; var f2=event.isImmediatePropagationStopped; alert(f1===f2);//返回true //中间有一次调用,如果有一次调用,那么把引用换做是另外一个函数,那么前后的引用就发生变化了,可以通过这种形式来判断是否调用了函数 //event.stopImmediatePropagation();这样不用每次都调用函数而求的返回值! var f1=event.isImmediatePropagationStopped; event.stopImmediatePropagation(); //这里调用多次也不会改变后面的false结果!所以也就说jQuery不会防止你多次调用stopImmediatePropagation方法 var f2=event.isImmediatePropagationStopped; alert(f1===f2);//返回false } );
如果调用了jQuery.Event对象的isImmediatePropagation那么会把event的isImmediateProgationStopped的函数句柄修改为另外一个函数!
jQuery.Event源码:
jQuery.Event = function( src, props ) { // Allow instantiation without the 'new' keyword //即使没有new操作符也能够构建jQuery.event对象 if ( !(this instanceof jQuery.Event) ) { return new jQuery.Event( src, props ); } // Event object //如果是click调用方式,那么走的就是这里的逻辑,originalEvent就是DOM中的事件[object MouseEvent] //传入的src是一个事件对象 if ( src && src.type ) { this.originalEvent = src; this.type = src.type; // Events bubbling up the document may have been marked as prevented // by a handler lower down the tree; reflect the correct value. this.isDefaultPrevented = src.defaultPrevented || src.defaultPrevented === undefined && // Support: IE < 9, Android < 4.0 src.returnValue === false ? returnTrue : returnFalse; // Event type } else { this.type = src; } // Put explicitly provided properties onto the event object if ( props ) { jQuery.extend( this, props ); } // Create a timestamp if incoming event doesn't have one this.timeStamp = src && src.timeStamp || jQuery.now(); // Mark it as fixed this[ jQuery.expando ] = true; }
preventDefault函数源码:
preventDefault: function() { var e = this.originalEvent; //调用preventDefault()函数以后,我们把isDefaultPrevented设置为returnTrue函数,然后再去实际上阻止这种默认行为! this.isDefaultPrevented = returnTrue; if ( !e ) { return; } //调用preventDefault或者returnValue=false // If preventDefault exists, run it on the original event if ( e.preventDefault ) { e.preventDefault(); // Support: IE // Otherwise set the returnValue property of the original event to false } else { e.returnValue = false; } }stopPropagation源码分析:
stopPropagation: function() { var e = this.originalEvent; //这个isPropagationStopped方法用在dispatch,trigger中被调用,这里仅仅是进行了引用,不是调用! //dispatch方法中的判断:event.isPropagationStopped() this.isPropagationStopped = returnTrue; if ( !e ) { return; } // If stopPropagation exists, run it on the original event //如果有stopPropagation,就直接调用stopPropagation,否则cancelBubble=true if ( e.stopPropagation ) { e.stopPropagation(); } // Support: IE // Set the cancelBubble property of the original event to true e.cancelBubble = true; }stopImmediatePropagation源码分析:
stopImmediatePropagation: function() { var e = this.originalEvent; //修改属性isImmediatePropagationStopped //alert(e.isImmediatePropagationStopped);打印function E(){return !1;} this.isImmediatePropagationStopped = returnTrue; // alert(e.originalEvent.stopImmediatePropagation); //打印function stopImmediatePropagation(){[native code]}这说明原生的event有stopImmediatePropagation方法 if ( e && e.stopImmediatePropagation ) { e.stopImmediatePropagation(); } this.stopPropagation(); }
总结:
(1)相比于stopPropagation函数,stopImmediatePropagation会结束后面所有的同类事件的执行(如一个元素绑定了多个click只会触发第一个),同时所有父类的元素也不会接收到该事件。但是stopPropagation函数会执行一个元素上面绑定的多个同类事件,只是不会冒泡!
(2)在stopImmediatePropagation中,如果JS原生的事件对象不存在stopImmediatePropagation方法,那么直接调用,否则调用stopPropagation!
(4)通过new Date(jQuery.now()).toLocaleString()可以获取到当前时间的本地显示,实际上是通过jQuery.now()获取当前时间的毫秒数!JS中可以通过+new Date()获取当前时间的毫秒数!或者也可以通过new Date().getTime()方法获取!