首页 > 代码库 > Event in Backbone

Event in Backbone

本文主要讲下Bacbone中的事件系统,先声明一个工具类:

 1 var slice = Array.prototype.slice; 2     _ = (function () { 3         var _ = function () { }; 4         _.extend = function (target) { 5             var sources = slice.call(arguments, 1); 6             sources.forEach(function (source) { 7                 if (source) { 8                     for (var prop in source) { 9                         target[prop] = source[prop];10                     }11                 }12             });13             return target;14         }15 16         var idCounter = 0;17         _.uniqueId = function (prefix) {18             var id = ++idCounter + ‘‘;19             return prefix ? prefix + id : id;20         };21         return _;22 })();

事件系统的大体框架:

 1 jass=(function(){ 2 var bone={}; 3 bone.Events={ 4    on: function (event, callback, context) { 5    }, 6    off: function (event, callback, context) { 7    }, 8   listenTo: function (otherObj, event, callback) { 9   },10   stopListening: function (otherObj, event, callback) {11   },12   trigger: function (event) {13   }14 15 }16      return bone;17 })();

on/off方法:

 1       on: function (event, callback, context) { 2           this._events || (this._events = {}); 3           var events = this._events[event] || (this._events[event] = []); 4           events.push({ callback: callback, context: context, ctx: context || this }); 5           return this; 6       }, 7       off: function (event, callback, context) { 8           if (!event && !callback) { 9               this._events = {};10               return this;11           }12           delete this._events[event];13       }

这两方法的原理和zepto中的on/off两方法差不多,不同的是,这里不再处理DOM元素上的事件:

 listenTo/stopListening方法:

 1       listenTo: function (otherObj, event, callback) { 2             var listeners = this._listeners || (this._listeners = {}); 3             var id = otherObj._listenerId || (otherObj._listenerId = _.uniqueId(‘1‘)); 4             listeners[id] = otherObj; 5             var onlyListener = !event && !callback; 6             if (onlyListener) return this; 7  8             if (typeof event === ‘object‘) callback = this; 9 10             otherObj.on(event, callback, this);11 12             return this;13       },14       stopListening: function (otherObj, event, callback) {15             var listeners = this._listeners;16             if (!listeners) return;17             var deleteListener = !event && !callback;18             if (typeof name === ‘object‘) callback = this;19             if (otherObj) (listeners = {})[otherObj._listenerId] = otherObj;20             for (var id in listeners) {21                 listeners[id].off(event, callback, this);22                 if (deleteListener) delete this._listeners[id];23             }24             return this;25       }

我们看到,listenTo是通过本对象给另外一个对象注册事件的.其内部调用了on方法,但是把另外的对象记录在其listeners属性中:这样做的好处可以从stopListening方法就能看到,通过listenTo方法注册的事件,都能通本对象的stopListening方法移除掉其他对象上的事件,消除对其他对象的影响.

trigger方法:

 1     trigger: function (event) { 2             if (!this._events) return this; 3             var args = slice.call(arguments, 1); 4             var events = this._events[event]; 5  6             if (events) { 7                 events.forEach(function (ev) {  8                     ev.callback.apply(ev.ctx, args); 9                 });10             }11            //处理all事件12             var allEvents = this._events.all;13             if (allEvents) {14                 allEvents.forEach(function (ev) {15                     ev.callback.apply(ev.ctx,args);16                 });17             }18         }

我们知道,在MVC中,视图层是会被频繁创建的,有创建就会有销毁。那一个视图关闭后,我们是不是要做些什么呢?看一个熟悉的场景:

 1 MyView = Backbone.View.extend({ 2   initialize: function(){ 3     this.listenTo (this.model,’change’, this); 4   }, 5   render: function(){ ... } 6 }); 7  8 Backbone的view类有个remove方法:
9 remove: function() {10 this.$el.remove();11 this.stopListening();12 return this;13 }

看到这个方法,是不是有点要清理view的感觉呢?但是遗憾的是,Backbone是不会调用它的,我们要自己添加一个(dispose/destroy)清理方法来封装这个remove,来帮我们处理销毁一个视图后的善后工作.

想想这里为何用listenTo,而不用on !