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 !

 

原文地址:https://www.cnblogs.com/stenson/p/3929081.html