Dalam artikel sebelumnya, saya memperkenalkan anda kepada jQuery-1.9.1 siri analisis kod sumber (10) seni bina acara sistem acara Artikel ini terus memperkenalkan kepada anda pengetahuan yang berkaitan tentang jquery1. 9.1 siri analisis kod sumber Sila lihat di bawah untuk butiran.
Pertama sekali, anda perlu memahami bahawa peristiwa asli penyemak imbas adalah baca sahaja, yang mengehadkan operasi jQuery padanya. Contoh mudah akan membantu anda memahami mengapa jQuery mesti membina objek acara baharu.
Dalam pemprosesan perwakilan, nod a mewakilkan nod b untuk melaksanakan fungsi fn apabila a diklik. Apabila acara buih ke nod b, persekitaran konteks perlu betul semasa melaksanakan fn Nod a yang melaksanakan fn, bukan nod b. Bagaimana untuk memastikan bahawa konteks pelaksanaan fn ialah nod a: lihat pada kod sumber (bahagian merah)
//执行 ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler ).apply( matched.elem, args );
Gunakan guna untuk menggantikan konteks fungsi pelaksanaan dengan nod (matched.elem). Perkara lain ialah args[0] ialah acara objek acara. Bagaimana untuk memastikan bahawa peristiwa itu adalah peristiwa nod a? Ini ialah fungsi peristiwa atribut penting.currentTarget, jadi satu langkah dilakukan sebelum melaksanakan apply
event.currentTarget = matched.elem;
Tukar secara langsung sifat Sasaran semasa objek acara, yang tidak boleh dilakukan dalam acara setempat penyemak imbas. Itulah sebabnya kami mempunyai objek acara jQuery yang dibina berdasarkan acara tempatan.
Terdapat dua jenis acara: acara tetikus dan acara papan kekunci (saya tidak tahu bila acara sentuh boleh ditambah). Lihat sifat terperinci kedua-dua
ini
Sebahagian daripadanya adalah khusus pelayar dan bukan piawaian W3C. jQuery membahagikan sifat acara kepada tiga bahagian
Sifat yang dikongsi oleh acara tetikus dan papan kekunci jQuery.event.props: "altKey buih boleh dibatalkan ctrlKey currentTarget eventFasa metaKey relatedTarget shiftKey sasaran timeStamp view which".split(" ")
Sifat khusus acara papan kekunci jQuery.event.keyHooks.props: "char charCode key keyCode".split(" ")
Sifat khusus acara tetikus jQuery.event.mouseHooks.props: "butang butang clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" ")
a. Bina objek acara baharu jQuery.event.fix(originalEvent)
Membina objek acara baharu selesai dalam tiga langkah
Dalam langkah pertama, gunakan event = new jQuery.Event(originalEvent) untuk membina objek acara baharu (jika anda tidak memahami peranan baharu, sila klik di sini), dan tambah isDefaultPrevented, originalEvent, taip dan timeStamp semasa mencipta acara Dan tanda acara telah diperbetulkan (penggunaan dioptimumkan untuk mengelakkan pemprosesan yang tidak perlu). Kod sumber jQuery.Event(src, props) adalah seperti berikut
jQuery.Event = function( src, props ) { // Allow instantiation without the 'new' keyword if ( !(this instanceof jQuery.Event) ) { return new jQuery.Event( src, props ); } //src为事件对象 if ( src && src.type ) { this.originalEvent = src; this.type = src.type; //事件冒泡的文档可能被标记为阻止默认事件发生;这个函数可以反应是否阻止的标志的正确值 this.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false || src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse; //src为事件类型 } else { this.type = src; } //将明确提供的特征添加到事件对象上 if ( props ) { jQuery.extend( this, props ); } //创建一个时间戳如果传入的事件不只一个 this.timeStamp = src && src.timeStamp || jQuery.now(); //标记事件已经修正过 this[ jQuery.expando ] = true; };
Objek acara yang dibina dalam langkah pertama
Langkah kedua ialah mengenal pasti jenis acara acara semasa, dan kemudian salin atribut yang sepadan satu demi satu daripada acara asal acara tempatan penyemak imbas
//创建可写的事件对象副本,并格式化一些特征名称 var i, prop, copy, type = event.type, originalEvent = event, fixHook = this.fixHooks[ type ]; if ( !fixHook ) { this.fixHooks[ type ] = fixHook = //rmouseEvent=/^(?:mouse|contextmenu)|click/ rmouseEvent.test( type ) ? this.mouseHooks : //rkeyEvent=/^key/ rkeyEvent.test( type ) ? this.keyHooks : {}; } //获得要从原生事件中拷贝过来的属性列表 copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props; ... //将原生的属性都拷贝到新的事件上 i = copy.length; while ( i-- ) { prop = copy[ i ]; event[ prop ] = originalEvent[ prop ]; }
Langkah ketiga ialah pemprosesan keserasian atribut berkaitan
// IE<9修正target特征值 if ( !event.target ) { event.target = originalEvent.srcElement || document; } // Chrome 23+, Safari?,Target特征值不能是文本节点 if ( event.target.nodeType === 3 ) { event.target = event.target.parentNode; } // IE<9,对于鼠标/键盘事件, 如果metaKey没有定义则设置metaKey==false event.metaKey = !!event.metaKey; //调用hooks的filter return fixHook.filter ? fixHook.filter( event, originalEvent ) : event;
Barisan terakhir kod melakukan pemprosesan penyesuaian yang serasi untuk acara tetikus dan acara papan kekunci.
fixHook.filter mungkin jQuery.event.keyHooks.filter
keyHooks.filter: function( event, original ) { //给键盘事件添加which特征值 if ( event.which == null ) { event.which = original.charCode != null ? original.charCode : original.keyCode; } return event; }
atau jQuery.event.mouseHooks.filter ini
mouseHooks.filter: function( event, original ) { var body, eventDoc, doc, button = original.button, fromElement = original.fromElement; //如果事件pageX/Y特征不见了,用可用的clientX/Y来计算出来 if ( event.pageX == null && original.clientX != null ) { eventDoc = event.target.ownerDocument || document; doc = eventDoc.documentElement; body = eventDoc.body; event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 ); event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 ); } //如果必要的话添加relatedTarget特征 if ( !event.relatedTarget && fromElement ) { event.relatedTarget = fromElement === event.target ? original.toElement : fromElement; } //添加点击事件which特征值: 1 === left; 2 === middle; 3 === right //备注:button不标准,因此不要是使用 if ( !event.which && button !== undefined ) { event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) ); } return event; }
Objek acara terkini yang dilengkapkan adalah seperti berikut (mengambil acara tetikus sebagai contoh)
Acara asal disimpan dalam OriginalEvent, sasaran menyimpan nod sasaran (nod yang diwakilkan, sumber acara) dan maklumat lain dilangkau
b. Kaedah acara lebihan
Apabila membina acara objek acara baru = new jQuery.Event(originalEvent), acara akan mewarisi kaedah dalam jQuery.event.prototype. Mari kita lihat kaedahnya
Kami sebelum ini menganalisis peranan kaedah stopPropagation terlampau beban dalam jQuery.event.prototype: selain memanggil kaedah objek acara untuk mengelakkan menggelegak, terdapat juga peranan apabila nod yang diwakilkan mempunyai berbilang acara yang diwakilkan menunggu untuk diproses. , salah satu acara yang memanggil event.stopPropagation() akan menghalang pelaksanaan pemprosesan acara berikutnya. Klik di sini untuk mencari kata kunci untuk melihat
Fungsi preventDefault juga mempunyai kesan yang sama. Kod ini telah ditambahkan pada fungsi preventDefault
this.isPropagationStopped = returnTrue;
在触发事件trigger函数和模拟冒泡simulate函数中都会根据isPropagationStopped()判断是否要执行DOM节点的默认操作。源码如下
isImmediatePropagationStopped是stopPropagation特殊用法,isImmediatePropagationStopped会直接阻止掉当前的处理和后面等待执行的事件处理,而stopPropagation会执行完当前的处理,然后阻止后面等待执行的事件处理。
源码如下
// jQuery.Event基于DOM事件所指定的ECMAScript语言绑定 // http://www.w.org/TR//WD-DOM-Level--Events-/ecma-script-binding.html jQuery.Event.prototype = { isDefaultPrevented: returnFalse, isPropagationStopped: returnFalse, isImmediatePropagationStopped: returnFalse, preventDefault: function() { var e = this.originalEvent; this.isDefaultPrevented = returnTrue; if ( !e ) {return; } if ( e.preventDefault ) { e.preventDefault(); //IE支持 } else { e.returnValue = false; } }, stopPropagation: function() { var e = this.originalEvent; this.isPropagationStopped = returnTrue; if ( !e ) {return; } if ( e.stopPropagation ) { e.stopPropagation(); } // IE支持 e.cancelBubble = true; }, stopImmediatePropagation: function() { this.isImmediatePropagationStopped = returnTrue; this.stopPropagation(); } }
以上就是本文给大家介绍的jQuery-1.9.1源码分析系列(十)事件系统之事件包装,希望大家喜欢。