当前位置:嗨网首页>书籍在线阅读

26-讨论

  
选择背景色: 黄橙 洋红 淡粉 水蓝 草绿 白色 选择字体: 宋体 黑体 微软雅黑 楷体 选择字体大小: 恢复默认

9.6.3 讨论

1.重载需要的方法

首先,创建一个函数,用自己的函数替代jQuery方法。将其命名为 jQuery.broadcast() ,如果你喜欢其他名称,可以修改:

(function($){
   $.broadcast = function(name){
     // 保存原始方法
     var old = $.fn[name];
     $.fn[name] = function(){
        // 广播
     };
   };
})(jQuery);

name 必须是我们想要覆盖的方法名称,例如:

jQuery.broadcast('addClass');

2.在执行之前触发一个事件

既然我们将自己的方法当作jQuery方法,就让我们来看看如何触发一个事件,使我们能够修改输入的参数:

//创建一个事件对象
 var e = $.Event('before-'+name);
 // 将参数保存到对象中
 e.args = $.makeArray(arguments);
 //触发事件
 this.trigger(e);

假定要广播 addClass() ,现在可以这么做:

jQuery('body').bind('before-addClass',function(e){
 e.args[0]; // CSS类
});

3.执行原始方法

现在触发一个事件,但是仍然必须调用旧的 addClass() 。因为将把返回的数据保存在事件对象中,所以在触发其他事件的时候,仍然可以提供这些数据。

e.ret = old.apply(this, e.args);

正如你所看到的,不传递原始的 arguments 数组,而用自己提供的数据代替,以防它们以某种方式修改。

4.在执行之后触发事件

现在将返回的数据保存在事件对象中,可以触发最后一个事件,允许已返回数据的外部修改。

重用同一个事件对象,但是修改事件的名称。

e.type = 'after-'+name;
this.trigger(e);

5.返回结果

现在剩下的工作就是返回结果数据,继续正常的执行流程。将返回保存在 e.ret上 的数据,该数据可能已经被某个事件处理程序修改:

return e.ret;

6.全部整合到一起

下面是开发的完整代码:

(function($){
   $.broadcast = function(name){
     var old = $.fn[name];
     $.fn[name] = function(){
        var e = $.Event('before-'+name);
        e.args = $.makeArray(arguments);
        this.trigger(e);
        e.ret = old.apply(this, e.args);
        e.type = 'after-'+name;
        this.trigger(e);
        return e.ret;
     };
   };
})(jQuery);

7.还有哪些可以改进之处

我尽量保持示例简明扼要。对这个例子还有许多可以改进的地方,下面是几种思路:

  • 使用 triggerHandler() 代替 trigger() :如果不需要事件冒泡,可以简单地使用 triggerHandler() ,这个方法会使整个过程更快;注意, triggerHandler() 只触发集合中第一个元素上的事件。
  • 在每个元素上单独运行:在前面的例子中, trigger() 在整个集合上运行一次。对于大多数情况这是没有问题的,但是当用在有多个元素的集合上时可能得到出乎意料的结果。

可以调用 map() 包装在函数中放入的功能,这能使代码在每个元素上都运行一次。

这样做的缺点是速度可能稍慢,由于调用 map() ,还将生成一个(预期之外)的栈条目。

  • 允许外部代码阻止正常地执行:如果使用的是jQuery 1.3或者更高版本,可以利用 jQuery.Event 的方法。

可以用 e.isDefaultPrevented() “询问”事件对象是否有其他代码调用了它的 preventDefault() 方法。

如果 e.isDefaultPrevented() 返回 true ,就不要调用原始函数。

  • 避免多次重载同一jQuery方法:这很简单;只要创建一个内部对象,记录重载的方法,然后只要忽略重复的调用就可以了。
  • jQuery.event.special 集成:这样就不必为所要重载的每个方法调用 jQuery.broadcast() 了。

作为替代,为每个方法在 jQuery.event.special 中添加一个条目,当其他代码绑定事件的时候从内部调用 jQuery.broadcast() 。这应该与重复调用的检查组合使用。