读jQuery之十四 (触发事件核心方法)

在 事件模块的演变 我使用了dispatchEvent(标准) 和fireEvent(IE)来主动触发事件。如下


代码如下:

...
dispatch = w3c ?
function(el, type){
try{
var evt = document.createEvent('Event');
evt.initEvent(type,true,true);
el.dispatchEvent(evt);
}catch(e){alert(e)};
} :
function(el, type){
try{
el.fireEvent('on'+type);
}catch(e){alert(e)}
};
...

jQuery则完全没有用到dispatchEvent/fireEvent方法。它采用的是另外一种机制。
jQuery触发事件的核心方法是jQuery.event.trigger。它提供给客户端程序员使用的触发事件方法有两个:.trigger/.triggerHandler

一个事件的发生在某些元素中可能会导致两种动作,一个是默认行为,一个是事件handler。如链接A
<a href="http://mail.sina.com.cn" onclick="alert(1);">新浪邮箱</a>
点击后,弹出1(事件handler),点确定跳转(默认行为)到了mail.sina.com.cn。因此,设计的触发事件的函数要考虑到这两种情况。
jQuery使用.trigger和.triggerHandler区分了这两种情况:
.trigger 执行事件hanlder/执行冒泡/执行默认行为
.triggerHandler 执行事件handler/不冒泡/不执行默认行为


代码如下:

.trigger/.triggerHandler的源码如下
trigger: function( type, data ) {
return this.each(function() {
jQuery.event.trigger( type, data, this );
});
},
triggerHandler: function( type, data ) {
if ( this[0] ) {
return jQuery.event.trigger( type, data, this[0], true );
}
},

可以看出,两者都调用jQuery.event.trigger。调用时一个没有传true,一个传了。传了true的triggerHander就表示仅执行事件handler。
此外还需注意一点区别:.trigger是对jQuery对象集合的操作,而.triggerHandler仅操作jQuery对象的第一个元素。如下


代码如下:

<p>p1</p>
<p>p1</p>
<p>p1</p>
<script>
$('p').click(function(){alert(1)});
$('p').trigger('click'); // 弹3次,即三个p的click都触发了
$('p').triggerHandler('click'); // 仅弹1次,即只触发第一个p的click
</script>

好了,是时候贴出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 ( type.indexOf("!") >= 0 ) {
// Exclusive events trigger only for the exact event (no namespaces)
type = type.slice(0, -1);
exclusive = true;
}

这一段是为了处理.trigger('click!')的情形,即触发非命名空间的事件。变量exclusive挂在事件对象上后在jQuery.event.handle内使用。举个例子


代码如下:

function fn1() {
console.log(1)
}
function fn2() {
console.log(2)
}
$(document).bind('click.a', fn1);
$(document).bind('click', fn2);
$(document).trigger('click!'); // 2

为document添加了两个点击事件,一个是具有命名空间的"click.a",一个则没有"click"。使用trigger时参数click后加个叹号"!"。从输出结果为2可以看出不触发命名空间的事件。总结一下:
.trigger('click') 触发所有的点击事件
.trigger('click.a') 仅触发“click.a” 的点击事件
.trigger('click!') 触发非命名空间的点击事件
接着看


代码如下:

if ( type.indexOf(".") >= 0 ) {
// Namespaced trigger; create a regexp to match event type in handle()
namespaces = type.split(".");
type = namespaces.shift();
namespaces.sort();
}

这段就很好理解了,就是对.trigger('click.a')的处理,即对具有命名空间事件的处理。
接着看


代码如下:

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( type, event ) :
// Just the event type (string)
new jQuery.Event( type );

有三种情况
,event 本身就是jQuery.Event类的实例
,event是个普通js对象(非jQuery.Event类的实例)
,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 ( !elem ) {
// 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 ) : [];
data.unshift( event );

先将参数data放入数组,event对象放在数组的第一个位置。
接着是


代码如下:

// Fire event on the current element, then bubble up the DOM tree
do {
var handle = jQuery._data( cur, "handle" );
event.currentTarget = cur;
if ( handle ) {
handle.apply( cur, data );
}
// Trigger an inline bound script
if ( ontype && jQuery.acceptData( cur ) && cur[ ontype ] && cur[ ontype ].apply( cur, data ) === 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方式添加的事件(如onclick="fun()")
,取父元素
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( elem, "a" )) && jQuery.acceptData( elem ) ) {
// 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 (#1486), 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 ( old ) {
elem[ ontype ] = null;
}
jQuery.event.triggered = type;
elem[ type ]();
}
} catch ( ieError ) {}
if ( old ) {
elem[ ontype ] = old;
}
jQuery.event.triggered = undefined;
}
}

这一段是对于浏览器默认行为的触发。如form.submit(),button.click()等。
注意,由于Firefox中链接的安全性限制,jQuery对链接的默认行为都统一为不能触发。即不能通过.trigger()使链接跳转。

(0)

相关推荐

  • jquery实现input输入框实时输入触发事件代码

    复制代码 代码如下: <input id="productName" name="productName" class="wid10" type="text" value="" /> 复制代码 代码如下: //绑定商品名称联想 $('#productName').bind('input propertychange', function() {searchProductClassbyName()

  • jquery实现勾选复选框触发事件给input赋值

    代码如下: 复制代码 代码如下: <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>jquery点击复选框触发事件给input赋值-柯乐义</title><base target="_blank" /> <style type="text/css"> * { marg

  • jQuery实现长按按钮触发事件的方法

    本文实例讲述了jQuery实现长按按钮触发事件的方法.分享给大家供大家参考.具体分析如下: 现在手机端的快速发展,使许多手机手势需要制作到手机版的网页过程中 网上有许多长按按钮的插件,甚至仅仅是jQuery Mobile都有长按事件 但是基于种种的兼容性问题, 只使用jquery去实现长按动作,可以在手机端与电脑端保持极强的兼容性 一.基本目标 制作一个按钮,实质上一个100x100px的灰色背景的图层,长按达2s则图层里的文字从in变成out.如下图所示: 二.制作过程 代码如下: 复制代码

  • jquery实现按Enter键触发事件示例

    复制代码 代码如下: $(function () { document.onkeydown = function (event) { var e = event || window.event || arguments.callee.caller.arguments[0]; if (e && e.keyCode == 13) { //to do something; } }; });

  • JQuery自动触发事件的方法

    本文实例讲述了JQuery自动触发事件的方法.分享给大家供大家参考.具体如下: 常用模拟 有时候,需要通过模拟用户操作,来达到单击的效果.例如在用户进入页面后,就触发click事件,而不需要用户去主动单击. 在JQuery中,可以使用trigger()方法完成模拟操作.例如可以使用下面的代码来触发id为btn的按钮的click事件. $('#btn').trigger("click"); 这样,当页面加载完毕后,就会立刻输出想要的效果.也可以直接简写click(),来达到同样的效果:

  • JQuery触发事件例如click

    复制代码 代码如下: $('#jquery_ulsjcuiwqljksadjaspcjxzkhl li:eq(0) a').trigger('click'); $('#bt).click();

  • jQuery如何使用自动触发事件trigger

    有时候,需要通过模拟用户操作,来达到点击的效果,例如用户进入页面后 就触发click事件,而无需主动点击. 比如以下代码: <body> <a href="#" onclick="javascript:document.getElementById('d').innerHTML='x1'">点击1</a> <a href="#" onclick="javascript:document.getE

  • 解决jquery中动态新增的元素节点无法触发事件问题的两种方法

    比如做一个ajax读取留言列表的时候,每条留言后面有个回复按钮,class为"reply",如果你用的是$(".reply").click(function(){ //do something... }),想必后面通过ajax加载进来的列表中的回复按钮,点击事件会失效. 其实最简单的方法就是直接在标签中写onclick="",但是这样写其实是有点low的,最好的方式还是通过给类名绑定一个click事件. 解决jquery中动态新增的元素节点无法触

  • jquery实现输入框实时输入触发事件代码

    话不多说,请看代码 $('.aa').bind('input propertychange', function() { searchProductClassbyName(); }); function searchProductClassbyName() { 写函数内容 } 以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持我们!

  • JQuery文本改变触发事件如聚焦事件、失焦事件

    Juery中聚焦事件: 复制代码 代码如下: $("#id").focus(function(){ }); 失焦事件: 复制代码 代码如下: $("#id").blur(function(){ }); 但是文本改变事件却不能这样写: 复制代码 代码如下: $("#id").change(function(){ }); 文本改变事件可以这样写,propertychange是属性改变时触发事件 复制代码 代码如下: $("#id"

随机推荐