0 Comments

DOM 无关事件

发布于:2014-04-03  |   作者:广州网站建设  |   已聚集:人围观

DOM 无关事件

基于事件的编程非常强大,因为它能让你的应用架构充分解耦,让功能变得更加内聚且具有更好的可维护性。事件本质上是和DOM 无关的,因此你可以很容易地开发出一个事件驱动的库。这种模式称为发布/ 订阅(http://en.wikipedia.org/wiki/Publish/subscribe),这是一个很有用的模式。

发布/ 订阅(Pub/Sub)是一种消息模式,它有两个参与者:发布者和订阅者。发布者向某个信道(channel)发布一条消息,订阅者绑定这个信道,当有消息发布至信道时就会接收到一个通知。最重要的一点是,发布者和订阅者是完全解耦的,彼此并不知晓对方的存在。两者仅仅共享一个信道名称。

发布者和订阅者的解耦可以让你的应用易于扩展,而不必引入额外的交叉依赖和耦合,从而提高了应用的可维护性,添加额外功能也非常容易。

那么,应当如何在应用中使用发布/ 订阅(Pub/Sub)模式呢?你只需记录回调和事件名称的对应关系及调用它们的方法。看一下这个例子,这段代码中实现了PubSub 对象,用它可以添加并触发事件监听:


  1. var PubSub = {  
  2. subscribe: function(ev, callback) {  
  3. // 创建 _callbacks 对象,除非它已经存在了  
  4. var calls = this._callbacks || (this._callbacks = {});  
  5. // 针对给定的事件key 创建一个数组,除非这个数组已经存在  
  6. // 然后将回调函数追加到这个数组中  
  7. (this._callbacks[ev] || (this._callbacks[ev] = [])).push(callback);  
  8. return this;  
  9. },  
  10. publish: function() {  
  11. // 将arguments 对象转换为真正的数组  
  12. var args = Array.prototype.slice.call(arguments, 0);  
  13. // 拿出第1 个参数,即事件名称  
  14. var ev = args.shift();  
  15. // 如果不存在_callbacks 对象,则返回  
  16. // 或者如果不包含给定事件对应的数组  
  17. var list, calls, i, l;  
  18. if (!(calls = this._callbacks)) return this;  
  19. if (!(list = this._callbacks[ev])) return this;  
  20. // 触发回调  
  21. for (i = 0l = list.length; i < l; i++)  
  22. list[i].apply(this, args);  
  23. return this;  
  24. }  
  25. };  
  26. // 使用方法  
  27. PubSub.subscribe("wem", function(){  
  28. alert("Wem!");  
  29. });  
  30. PubSub.publish("wem"); 

广州网站建设,广州网站设计,广州网站制作,网站建设,网站设计,广州网站建设公司,广州网站设计公司

你可以使用命名空间的方式来管理事件名称,比如使用冒号分隔符(:)。

  1. PubSub.subscribe("user:create", function(){ /* ... */ }); 

 

如果你在使用jQuery,可以关注下Ben Alman(http://benalman.com)写的一个更容易的库(http://gist.github.com/799721/c119783954e1b10551c4afef53b2c04fefcb7465)。这个库非常简单,用不了一页纸:

  1. /*!  
  2. * jQuery Tiny Pub/Sub - v0.3 - 11/4/2010  
  3. * http://benalman.com/  
  4. *  
  5. * Copyright (c) 2010 "Cowboy" Ben Alman  
  6. * Dual licensed under the MIT and GPL licenses.  
  7. * http://benalman.com/about/license/  
  8. */  
  9. (function($){  
  10. var o = $({});  
  11. $.subscribe = function() {  
  12. o.bind.apply( o, arguments );  
  13. };  
  14. $.unsubscribe = function() {  
  15. o.unbind.apply( o, arguments );  
  16. };  
  17. $.publish = function() {  
  18. o.trigger.apply( o, arguments );  
  19. };  
  20. })(jQuery); 

 

这里的API 和jQuery 的bind() 及trigger() 函数的参数一致。唯一的区别就是这两个函数直接保存在jQuery 对象中,且名叫publish() 和subscribe() :

  1. $.subscribe( "/some/topic", function( event, a, b, c ) {  
  2. console.log( event.type, a + b + c );  
  3. });  
  4. $.publish( "/some/topic", "a", "b", "c" ); 

 

上面我们将Pub/Sub 用于全局事件,也能很容易地将其用于局部事件。现在我们用上面提到的PubSub 对象来创建一个对象的局部事件:

  1. var Asset = {};  
  2. // 添加PubSub  
  3. jQuery.extend(Asset, PubSub);  
  4. // 现在就可以用publish/subscribe 函数了  
  5. Asset.subscribe("create", function(){  
  6. // ...  
  7. }); 

广州网站建设,广州网站设计,广州网站制作,网站建设,网站设计,广州网站建设公司,广州网站设计公司

我们使用了jQuery 的extend() 来将PubSub 的属性复制至Asset 对象。这样的话,所有对publish() 和subscribe() 的调用均是针对Asset 的局部调用。这在很多场景中非常有用,包括对象关系映射(ORM)中的事件、状态机及当Ajax 请求结束时的回调等场景。
标签:
飞机