jQuery源码分析之jQuery.Event,$.stopImmediatePropagation,$.preventDefault,$.stopPropagation

请提前阅读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对象
  });
  });

测试代码2:

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中该属性用于保存数据!

测试代码7:

 <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()方法获取!

你可能感兴趣的:(jQuery源码分析之jQuery.Event,$.stopImmediatePropagation,$.preventDefault,$.stopPropagation)