18-讨论
9.4.3 讨论
1.在jQuery 1.3+中怎么做
从jQuery 1.3起,由于增加了 jQuery.Event ,上述任务可以用更漂亮的方式完成。旧的实现方式仍然可用于 triggerHandler() ,但是对 jQuery.trigger() 不起作用。
对于现在将要看到的代码,需要创建一个 jQuery.Event :
var e = jQuery.Event('updateName');
现在,为了调用处理程序和获取数值,将把事件对象传递给 trigger() ,然后从事件对象提取数据:
jQuery('#element').trigger(e);
alert( e.result ); // Charles
正如一开始时所说的那样,在绑定了许多处理程序时这种方法不能很好地工作,总的来说,这种方法有点不可靠和脆弱。
那么,如何进行事件处理程序和触发事件的函数之间的通信呢?
答案是,通过传递的事件对象。
传递给 trigger() 的 jQuery.Event 对象与每个处理程序接收的第一个参数相同。
这就意味着可以这么做:
jQuery('#name').bind('updateName', function(e){
e.name = this.value;
});
var e = jQuery.Event('updateName');
jQuery('#name').trigger(e);
alert( e.name );
上述例子与简单地访问 e.result 没有太大的不同,但是对于在同一个事件对象上操作的多个事件处理程序又是如何呢?
jQuery('#first').bind('update', function(e){
e.firstName = this.value;
});
jQuery('#last').bind('update', function(e){
e.lastName = this.value;
});
var e = jQuery.Event('update');
jQuery('#first, #last').trigger(e);
alert( e.firstName );
alert( e.lastName );
现在有了让任意数量的事件处理程序为函数提供运行所需数据的一种手段。不言而喻,可以多次调用 trigger() ,传递相同的事件对象。
前面已经说过,用默认值(如果恰当的话)预设事件对象是明智的。代码不应该依赖于其他代码对某个事件的订阅。
如果没有默认值可用,那么总是可以中断调用或者抛出一个错误。
2.在jQuery 1.3中如何实现
旧版本的jQuery只允许用户获得一个值,该值可以在调用 jQuery.trigger() 或者 triggerHandler() 时返回。
具体代码如下:
jQuery('#element').bind('updateName', function(){
return 'Charles';
});
var name = jQuery('#element').triggerHandler('updateName');
alert( name ); // Charles
在返回数据的事件处理程序不超过一个时,这种方法都没问题。在遇到多个事件处理器返回数据的情况时,按照“谁最后到”决定返回哪个处理器的数据。
3.允许事件处理程序阻止操作
这是我们刚刚看到的情况的一种特例。按照设计,事件对象有一个 preventDefault() 方法,该方法用在原生事件上,终止常用的操作(如链接上的单击),但是在自定义事件上没有实际的用途。
可以利用这个方法,允许其他脚本阻止将要执行的操作。
现在将展示一个操作的示例。虽然使用秘诀9.2介绍的小插件,但是毫无疑问,并不一定要使用它:
var remote = jQuery.listener({
request:function( url, callback ){
jQuery.ajax({ url:url, success:callback });
}
});
// 发出一个请求
remote.request('contact.html', function( html ){
alert( html );
});
现在,假定我们想允许外部脚本在必要时终止某些请求。需要这样修改 remote.request:
var remote = jQuery.listener({
request:function( url, callback ){
var e = jQuery.Event('beforeRequest');
e.url = url;
this.trigger(e);
if( !e.isDefaultPrevented() )
jQuery.ajax({ url:url, success:callback });
}
});
e.isDefaultPrevented() 的返回值表示在这个对象上是否调用过 e.preventDefault() 。
任何外部脚本现在都可以这么做:
remote.bind('beforeRequest', function(e){
if( e.url == 'contact.html' )
e.preventDefault();
});
返回false(在函数中)的效果和 e.preventDefault() 几乎相同,将停止事件传播,这正是我们预期的。
毫无疑问,在这种情况下,可以使用前面学到的知识,允许处理程序修改URL(或者发送添加的数据)。