- 问题引入,先贴一段有问题的代码,如果你对 trigger() 这个函数了解不透彻,还真看不出这段代码错在哪。完成的功能是样式转换器,想让页面在加载后自行触发点击事件隐藏三个按钮,但是效果如图并没有隐藏按钮们:控制台会报错: target 属性是 undefined ,肯定是 event 这个事件对象没获取到的问题,程序到17行出错停止,这让我感到疑问:自定义触发的事件难道没有event对象吗?。
1 <div id="switcher" class="switcher"> 2 <h3>Style Switcher</h3> 3 <button id="switcher-default">Default</button> 4 <button id="switcher-narrow">Narrow</button> 5 <button id="switcher-large">Large</button> 6 </div> 7 <script type="test/javascript"> 8 function func(){ 9 if(!$(event.target).is(‘button‘)){ 10 $(‘#switcher button‘).toggle(‘slow‘); 11 } 12 } 13 function setBodyClass(classname){ 14 //... 15 } 16 $(‘#switcher‘).on(‘click‘,function(){ 17 if($(event.target).is(‘button‘)){ 18 var classbody=event.target.id.split(‘-‘)[1]; 19 setBodyClass(classbody); 20 } 21 }).on(‘click‘,func); 22 $(‘#switcher‘).trigger(‘click‘); 23 </script>
- 问题思考,看看到底有没有事件对象, undefined 表明居然没有,千万别以为jQuery真的不支持自定义的事件对象其实这里是代码写的方式不对才导致 undefined ,后面会有详细代码验证!
1 $(‘#switcher‘).on(‘click‘,function(){ 2 //if($(event.target).is(‘button‘)){ 3 // var classbody=event.target.id.split(‘-‘)[1]; 4 //setBodyClass(classbody); 5 //} 6 console.log(event); 7 }); 8 9 $(‘#switcher‘).trigger(‘click‘);
迷惑不解的我查看了下jQuery官方文档最后一句说:“尽管 trigger() 模仿了激活事件的作用,完成与合成事件对象,它不完全复制的天然发生的事件”。为啥文档居然说有事件对象,只不过这个事件对象和天然的事件对象不一样。之前我还以为人工触发是不是就没有 event 事件对象,人工触发只是在机械地执行事件处理程序才导致的 undefined 。。。
As of jQuery 1.3,
.trigger()
ed events bubble up the DOM tree; an event handler can stop the bubbling by returningfalse
from the handler or calling the.stopPropagation()
method on the event object passed into the event. Although.trigger()
simulates an event activation, complete with a synthesized event object, it does not perfectly replicate a naturally-occurring event.
既然没有 event 就执行不了,那就造一个事件对象,看到官网给了这样的示例,自行创建一个 jQuery.Event() 的实例事件对象:
var event = jQuery.Event( "submit" );
$( "form:first" ).trigger( event );
if ( event.isDefaultPrevented() ) {
// Perform an action...
}
- 问题验证,相应我的代码就要改成:(这也是创建 jQuery.Event 实例对象方式一)
1 $(‘#switcher‘).on(‘click‘,function(event){ 2 if($(event.target).is(‘button‘)){ 3 var classbody=event.target.id.split(‘-‘)[1]; 4 setBodyClass(classbody); 5 } 6 console.log(event) 7 }).on(‘click‘,func); 8 9 var e=jQuery.Event(‘click‘);//可以省略new 关键字 10 $(‘#switcher‘).trigger(e);
看看这个自创的事件对象是什么东西, target 属性终于是我想要的了。
- 1.使用 triggle() 应注意的问题,同一个元素的自定义的触发代码要写在其绑定事件处理程序代码之后,不然执行自定义触发代码时找不到事件处理程序会告终而亡。
2.创建 jQuery.Event 实例对象方式二 ele.trigger(‘eventType‘) 直接创建
//包含事件处理程序1 1 $(document).ready(function(){ 2 $(‘#switcher‘).trigger(‘click‘); 3 }) //包含事件处理程序2 4 $(‘#switcher‘).on(‘click‘,function(){ 5 console.log(event); 6 if($(event.target).is(‘button‘)){ 7 var classbody=event.target.id.split(‘-‘)[1]; 8 setBodyClass(classbody); 9 } 10 })
target 是 document ,可以看出 trigger() 如果不传参事件对象,则事件处理程序2的 event 是上一个事件对象即执行 $(‘#switcher‘).trigger(‘click‘); 所在事件处理程序1里的事件对象。若传了事件对象的参数则会将事件处理程序2中的默认传入的 event 覆盖掉成为新的由 trigger() 触发的事件对象(上面的 document 例子)或直接传入由 trigger() 触发的事件对象(事件处理程序2现在没有 event 所以不用覆盖,下面例子):
1 $(‘#switcher‘).on(‘click‘,function(event){ 2 console.log(event); 3 if($(event.target).is(‘button‘)){ 4 var classbody=event.target.id.split(‘-‘)[1]; 5 // setBodyClass(classbody); 6 } 7 }) 8 $(‘#switcher‘).trigger(‘click‘);
这个由 trigger() 触发得来的事件对象是 jQuery.Event() 的实例对象,看到 target 属性正确我就放心了。
- 总结:创建自定义的事件对象有两种方式,你可以用 ele.trigger(‘eventType‘); 自定义触发事件(当然这句一执行就自动构造了一个 jQuery.Event 实例事件对象),也可以用不带 new 关键字构造事件对象。但传不传这个事件对象的参数就看你事件处理程序中需要不需要了,不传意味着事件处理程序里的 event 为 undefined (在不存在上一个事件对象情况下)或使用上一个 event 事件对象,传了就意味着事件处理程序中的事件对象是由 trigger() 得来的 jQuery.Event 实例对象。
- 参考:http://api.jquery.com/trigger/