A-A+

JQuery触发事件多实例讲解

2016年01月08日 前端设计 暂无评论 阅读 6 views 次

触发事件,或称模拟用户动作。在js中,如果我们要触发一个按钮的点击事件,直接使用元素的onclick事件,然后调用相关函数就可以了。下面是我整理的一些触发事件实例。

JQuery触发事件使代码分离,在js中,如果我们要触发一个按钮的点击事件,直接使用元素的onclick事件,然后调用相关函数就可以了,这样的 写法则是让代码与html结合到一起了,在Jquery中就不用这样了,它有另外的几种写法,可以使代码与html分开,比如页面中有一个按钮:

  1. <input id="btn" type="button" value="提交" />  

我们要触发它的点击事件可以有下面两种方式:

  1. 一:jQuery(function($){  
  2. $("#btn").click(function(){alert("这是触发事件的第一种方式")})  
  3. })  

直接获得元素,然后调用click方法就可以了,函数在事件里面写.

  1. 二:jQuery(document).ready(function()  
  2. {  
  3. $("#btn1").bind("click",function(event){  
  4. alert("这是触发事件的第二种方式")  
  5. })  
  6. }   )  

这种方法是绑定事件.

上面两种方式都可以,其中click可以换成其他的blur,focus等事件

如果是一个元素要触发两次事件,比如失去焦点,获取焦点,在js中要用到onfocus和onblur事件,在jquery中直接连续添加即可,代码如下:

  1. $(function(){  
  2. $("#txtName").focus(function(){  
  3. $("#txtName").attr("value","");  
  4. }).blur(function(){  
  5. $("#txtName").addClass("aa");  
  6. });  
  7. })  

或者代码如下:

  1. $(function(){  
  2. $("#txtName").focus(function(){  
  3. $(this).attr("value","");  
  4. }).blur(function(){  
  5. $(this).addClass("aa");  
  6. });  
  7. })  

this代表当前元素,或者使用bind绑定两次事件都可以,触发事件,或称模拟用户动作。比如点击,我们可以用代码去模拟用户点击,达到的效果与真实的鼠标点击是一样的。在事件模块的演变 我使用了dispatchEvent(标准) 和fireEvent(IE)来主动触发事件,代码如下:

  1. ...  
  2. dispatch = w3c ?  
  3.     function(el, type){  
  4.         try{  
  5.             var evt = document.createEvent('Event');  
  6.             evt.initEvent(type,true,true);  
  7.             el.dispatchEvent(evt);  
  8.         }catch(e){alert(e)};  
  9.     } :  
  10.     function(el, type){  
  11.         try{  
  12.             el.fireEvent('on'+type);  
  13.         }catch(e){alert(e)}  
  14.     };  
  15. ...  

jQuery则完全没有用到dispatchEvent/fireEvent方法。它采用的是另外一种机制。

jQuery触发事件的核心方法是jQuery.event.trigger。它提供给客户端程序员使用的触发事件方法有两个:trigger/triggerHandler

JQuery触发事件多实例讲解

一个事件的发生在某些元素中可能会导致两种动作,一个是默认行为,一个是事件handler,如链接A,代码如下:

  1. <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的源码如下:

  1. trigger: function( type, data ) {  
  2.     return this.each(function() {  
  3.         jQuery.event.trigger( type, data, this );  
  4.     });  
  5. },  
  6.    
  7. triggerHandler: function( type, data ) {  
  8.     if ( this[0] ) {  
  9.         return jQuery.event.trigger( type, data, this[0], true );  
  10.     }  
  11. },  

可以看出,两者都调用jQuery.event.trigger。调用时一个没有传true,一个传了。传了true的triggerHander就表示仅执行事件handler。

此外还需注意一点区别:trigger是对jQuery对象集合的操作,而triggerHandler仅操作jQuery对象的第一个元素,代码如下:

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

好了,是时候贴出jQuery.event.trigger的代码了,代码如下:

  1. trigger: function( event, data, elem, onlyHandlers ) {  
  2.     // Event object or event type  
  3.     var type = event.type || event,  
  4.         namespaces = [],  
  5.         exclusive;  
  6.    
  7.         ......  
  8.    
  9. }  

这就是jQuery.event.trigger的定义,省略了大部分,下面一一列举,代码如下:

  1. if ( type.indexOf("!") >= 0 ) {  
  2.     // Exclusive events trigger only for the exact event (no namespaces)  
  3.     type = type.slice(0, -1);  
  4.     exclusive = true;  
  5. }  

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

  1. function fn1() {  
  2.     console.log(1)  
  3. }  
  4. function fn2() {  
  5.     console.log(2)  
  6. }  
  7. $(document).bind('click.a', fn1);  
  8. $(document).bind('click', fn2);  
  9. $(document).trigger('click!'); // 2  

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

trigger('click') 触发所有的点击事件

trigger('click.a') 仅触发“click.a” 的点击事件

trigger('click!') 触发非命名空间的点击事件

接着看,代码如下:

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

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

接着看,代码如下:

  1. if ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) {  
  2.     // No jQuery handlers for this event type, and it can't have inline handlers  
  3.     return;  
  4. }  

对于一些特殊事件如"getData"或对于已经触发过的事件直接返回。

往下,代码如下:

  1. event = typeof event === "object" ?  
  2.     // jQuery.Event object  
  3.     event[ jQuery.expando ] ? event :  
  4.     // Object literal  
  5.     new jQuery.Event( type, event ) :  
  6.     // Just the event type (string)  
  7.     new jQuery.Event( type );  

有三种情况:

event 本身就是jQuery.Event类的实例

event是个普通js对象(非jQuery.Event类的实例)

event是个字符串,如"click"

续,代码如下:

  1. event.type = type;  
  2. event.exclusive = exclusive;  
  3. event.namespace = namespaces.join(".");  
  4. event.namespace_re = new RegExp("(^|.)" + namespaces.join(".(?:.*.)?") + "(.|$)");  

需要注意exclusive/namespace/namespace_re挂到了event上了,在jQuery.event.handle中可以用到(事件命名空间)。

往下是如下代码:

  1. // triggerHandler() and global events don't bubble or run the default action  
  2. if ( onlyHandlers || !elem ) {  
  3.     event.preventDefault();  
  4.     event.stopPropagation();  
  5. }  

onlyHandlers 只在 triggerHandler用到了,即不触发元素的默认行为,且停止冒泡。

下面是如下代码:

  1. // Handle a global trigger  
  2. if ( !elem ) {  
  3.     // TODO: Stop taunting the data cache; remove global events and always attach to document  
  4.     jQuery.each( jQuery.cache, function() {  
  5.         // internalKey variable is just used to make it easier to find  
  6.         // and potentially change this stuff later; currently it just  
  7.         // points to jQuery.expando  
  8.         var internalKey = jQuery.expando,  
  9.             internalCache = this[ internalKey ];  
  10.         if ( internalCache && internalCache.events && internalCache.events[ type ] ) {  
  11.             jQuery.event.trigger( event, data, internalCache.handle.elem );  
  12.         }  
  13.     });  
  14.     return;  
  15. }  

这里是个递归调用。如果没有传elem元素,那么从jQuery.cache里取。

接着是如下代码:

  1. // Don't do events on text and comment nodes  
  2. if ( elem.nodeType === 3 || elem.nodeType === 8 ) {  
  3.     return;  
  4. }  

属性,文本节点直接返回。

下面是如下代码:

  1. // Clone any incoming data and prepend the event, creating the handler arg list  
  2. data = data != null ? jQuery.makeArray( data ) : [];  
  3. data.unshift( event );  

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

接着是如下代码:

  1. // Fire event on the current element, then bubble up the DOM tree  
  2. do {  
  3.     var handle = jQuery._data( cur, "handle" );  
  4.    
  5.     event.currentTarget = cur;  
  6.     if ( handle ) {  
  7.         handle.apply( cur, data );  
  8.     }  
  9.    
  10.     // Trigger an inline bound script  
  11.     if ( ontype && jQuery.acceptData( cur ) && cur[ ontype ] && cur[ ontype ].apply( cur, data ) === false ) {  
  12.         event.result = false;  
  13.         event.preventDefault();  
  14.     }  
  15.    
  16.     // Bubble up to document, then to window  
  17.     cur = cur.parentNode || cur.ownerDocument || cur === event.target.ownerDocument && window;  
  18. while ( cur && !event.isPropagationStopped() );  

这段代码很重要,做了以下事情

取handle

执行

执行通过onXXX方式添加的事件(如onclick="fun()")

取父元素

while循环不断重复这四步以模拟事件冒泡。直到window对象

接下是如下代码:

  1. // If nobody prevented the default action, do it now  
  2. if ( !event.isDefaultPrevented() ) {  
  3.     var old,  
  4.         special = jQuery.event.special[ type ] || {};  
  5.    
  6.     if ( (!special._default || special._default.call( elem.ownerDocument, event ) === false) &&  
  7.         !(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) {  
  8.    
  9.         // Call a native DOM method on the target with the same name name as the event.  
  10.         // Can't use an .isFunction)() check here because IE6/7 fails that test.  
  11.         // IE<9 dies on focus to hidden element (#1486), may want to revisit a try/catch.  
  12.         try {  
  13.             if ( ontype && elem[ type ] ) {  
  14.                 // Don't re-trigger an onFOO event when we call its FOO() method  
  15.                 old = elem[ ontype ];  
  16.    
  17.                 if ( old ) {  
  18.                     elem[ ontype ] = null;  
  19.                 }  
  20.    
  21.                 jQuery.event.triggered = type;  
  22.                 elem[ type ]();  
  23.             }  
  24.         } catch ( ieError ) {}  
  25.    
  26.         if ( old ) {  
  27.             elem[ ontype ] = old;  
  28.         }  
  29.    
  30.         jQuery.event.triggered = undefined;  
  31.     }  
  32. }  

这一段是对于浏览器默认行为的触发。如form.submit(),button.click()等。

注意,由于Firefox中链接的安全性限制,jQuery对链接的默认行为都统一设计为不能触发。即不能通过trigger()使链接跳转。

Jquery 监视按键、回车键触发事件的实例

代码示例:

  1. <script type="text/javascript">  
  2. $(function () {  
  3. $('input:text:first').focus(); //把焦点放在第一个文本框  
  4. var $inp = $('input'); //所有的input元素  
  5. $inp.keypress(function (e) { //这里给function一个事件参数命名为e,叫event也行,随意的,e就是IE窗口发生的事件。  
  6.     var key = e.which; //e.which是按键的值  
  7.     if (key == 13) {  
  8.         alert("aaa");  
  9.     }  
  10. });  
  11.   
  12. });  

拖了一个Login控件,然后给它转化为template,用于自定义开发。

以上代码中捕捉到了文本栏的回车按键,这时要去触发LoginButton来提交登录信息进行验证,可是使用$("[id$=LoginButton]").click();只在firefox上有效,在IE无效,歪打正着的尝试一下$("[id$=LoginButton]").focus();,在ie下有效,在IE上focus()即完成了对焦又执行了点击,这是为什么呢?

  1. $inp.keypress(function (event) {  
  2.     var key = event.which;  
  3.     if (key == 13) {  
  4.         $("[id$=LoginButton]").click(); //支持firefox,IE武校  
  5.         //$('input:last').focus();  
  6.         $("[id$=LoginButton]").focus();  //支持IE,firefox无效。  
  7.   
  8. //以上两句实现既支持IE也支持 firefox  
  9.     }  
  10. });  
标签:

给我留言