威斯尼斯人官网读jQuery之十四 _jquery_脚本之家

在 事件模块的演变 我使用了dispatchEvent来主动触发事件。如下 复制代码 代码如下: … dispatch = w3c ?
function{ try{ var evt = document.createEvent; evt.initEvent;
el.dispatchEvent{alert}; } : function{ try{ el.fireEvent{alert} }; …
jQuery则完全没有用到dispatchEvent/fireEvent方法。它采用的是另外一种机制。
jQuery触发事件的核心方法是jQuery.event.trigger。它提供给客户端程序员使用的触发事件方法有两个:.trigger/.triggerHandler
一个事件的发生在某些元素中可能会导致两种动作,一个是默认行为,一个是事件handler。如链接A
新浪邮箱
点击后,弹出1,点确定跳转到了mail.sina.com.cn。因此,设计的触发事件的函数要考虑到这两种情况。
jQuery使用.trigger和.triggerHandler区分了这两种情况: .trigger
执行事件hanlder/执行冒泡/执行默认行为 .triggerHandler
执行事件handler/不冒泡/不执行默认行为 复制代码 代码如下:
.trigger/.triggerHandler的源码如下 trigger: function { return this.each
{ jQuery.event.trigger; }); }, triggerHandler: function { if { return
jQuery.event.trigger( type, data, this[0], true ); } },
可以看出,两者都调用jQuery.event.trigger。调用时一个没有传true,一个传了。传了true的triggerHander就表示仅执行事件handler。
此外还需注意一点区别:.trigger是对jQuery对象集合的操作,而.triggerHandler仅操作jQuery对象的第一个元素。如下
复制代码 代码如下:

好了,是时候贴出jQuery.event.trigger的代码了 复制代码 代码如下: trigger: function( event,
data, elem, onlyHandlers ) { // Event object or event type var type =
event.type || event, namespaces = [], exclusive; …… }
这就是jQuery.event.trigger的定义,省略了大部分。下面一一列举 复制代码 代码如下: if >= 0 ) { // Exclusive
events trigger only for the exact event type = type.slice; exclusive =
true; }
这一段是为了处理.trigger的情形,即触发非命名空间的事件。变量exclusive挂在事件对象上后在jQuery.event.handle内使用。举个例子
复制代码 代码如下: function fn1 }
function fn2 } $.bind; $.bind; $.trigger; // 2
为document添加了两个点击事件,一个是具有命名空间的”click.a”,一个则没有”click”。使用trigger时参数click后加个叹号”!”。从输出结果为2可以看出不触发命名空间的事件。总结一下:
.trigger 触发所有的点击事件 .trigger 仅触发“click.a” 的点击事件 .trigger
触发非命名空间的点击事件 接着看 复制代码
代码如下: if >= 0 ) { // Namespaced trigger; create a regexp to match
event type in handle() namespaces = type.split; type = namespaces.shift;
} 这段就很好理解了,就是对.trigger的处理,即对具有命名空间事件的处理。
接着看 复制代码 代码如下: if ( (!elem ||
jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] )
{ // No jQuery handlers for this event type, and it can’t have inline
handlers return; }
对于一些特殊事件如”getData”或对于已经触发过的事件直接返回。 往下 复制代码 代码如下: event = typeof event ===
“object” ? // jQuery.Event object event[ jQuery.expando ] ? event : //
Object literal new jQuery.Event : // Just the event type new
jQuery.Event; 有三种情况 ,event 本身就是jQuery.Event类的实例
,event是个普通js对象 ,event是个字符串,如”click” 续 event.type = type;
event.exclusive = exclusive; event.namespace = namespaces.join;
event.namespace_re = new RegExp” + namespaces.join + “;
需要注意exclusive/namespace/namespace_re挂到了event上了,在jQuery.event.handle中可以用到。
往下是 复制代码 代码如下: //
triggerHandler() and global events don’t bubble or run the default
action if ( onlyHandlers || !elem ) { event.preventDefault();
event.stopPropagation(); } onlyHandlers 只在
.triggerHandler用到了,即不触发元素的默认行为,且停止冒泡。 下面是 复制代码 代码如下: // Handle a global trigger
if { // TODO: Stop taunting the data cache; remove global events and
always attach to document jQuery.each( jQuery.cache, function() { //
internalKey variable is just used to make it easier to find // and
potentially change this stuff later; currently it just // points to
jQuery.expando var internalKey = jQuery.expando, internalCache = this[
internalKey ]; if ( internalCache && internalCache.events &&
internalCache.events[ type ] ) { jQuery.event.trigger( event, data,
internalCache.handle.elem ); } }); return; }
这里是个递归调用。如果没有传elem元素,那么从jQuery.cache里取。 接着是
复制代码 代码如下: // Don’t do events on
text and comment nodes if ( elem.nodeType === 3 || elem.nodeType === 8 )
{ return; } 属性,文本节点直接返回。 下面是 复制代码 代码如下: // Clone any incoming data
and prepend the event, creating the handler arg list data = data != null
? jQuery.makeArray : []; data.unshift;
先将参数data放入数组,event对象放在数组的第一个位置。 接着是 复制代码 代码如下: // Fire event on the current
element, then bubble up the DOM tree do { var handle = jQuery._data;
event.currentTarget = cur; if { handle.apply; } // Trigger an inline
bound script if ( ontype && jQuery.acceptData && cur[ ontype ] &&
cur[ ontype ].apply === false ) { event.result = false;
event.preventDefault(); } // Bubble up to document, then to window cur =
cur.parentNode || cur.ownerDocument || cur ===
event.target.ownerDocument && window; } while ( cur &&
!event.isPropagationStopped; 这段代码很重要,做了以下事情 ,取handle
,执行 ,执行通过onXXX方式添加的事件 ,取父元素
while循环不断重复这四步以模拟事件冒泡。直到window对象。 接下是 复制代码 代码如下: // If nobody prevented the
default action, do it now if ( !event.isDefaultPrevented { var old,
special = jQuery.event.special[ type ] || {}; if ( (!special._default
|| special._default.call( elem.ownerDocument, event ) === false) &&
!(type === “click” && jQuery.nodeName && jQuery.acceptData { // Call a
native DOM method on the target with the same name name as the event. //
Can’t use an .isFunction)() check here because IE6/7 fails that test. //
IE<9 dies on focus to hidden element , may want to revisit a
try/catch. try { if ( ontype && elem[ type ] ) { // Don’t re-trigger
an onFOO event when we call its FOO() method old = elem[ ontype ]; if
{ elem[ ontype ] = null; } jQuery.event.triggered = type; elem[ type
](); } } catch {} if { elem[ ontype ] = old; } jQuery.event.triggered
= undefined; } } 这一段是对于浏览器默认行为的触发。如form.submit等。
注意,由于Firefox中链接的安全性限制,jQuery对链接的默认行为都统一为不能触发。即不能通过.trigger()使链接跳转。

发表评论

电子邮件地址不会被公开。 必填项已用*标注

相关文章