backbone库学习-Events
backbone库的框架
http://www.cnblogs.com/nuysoft/archive/2012/03/19/2404274.html
我们先从backbone的Events模块开始
var Events = Backbone.Events ={}
var eventSplitter = /\s+/;
var eventsApi = function(obj, action, name, rest){}
var triggerEvents = function(events, args){}
var listenMethods = {listenTo: 'on', listenToOnce: 'once'};
_.each(listenMethods, function(implementation, method){}
Events.bind = Events.on;
Events.unbind = Events.off;
_.extend(Backbone, Events);
举个例子:
var m = new Backbone.Model();
m.on('show',function(){
alert('show')
}) m.trigger('show');
第一步:先实例化model模块,在实例上绑定了all的监听事件。最后调用trigger来触发。
注意看Events部分代码结构:
_.extend(Backbone, Events);
backbone依赖underscore.js库,_.extend是underscore.js库的方法。
我们来看一下:
_.extend = function(obj) {
each(slice.call(arguments, 1), function(source) {
if (source) {
for (var prop in source) {
obj[prop] = source[prop];
}
}
});
return obj;
};
根据以上代码,我们大概知道_.extend(Backbone,Events)的意思了,将Events的成员添加到Backbone。Backbone调用的方法名与Events调用的方法名一致。
继续看例子
m.on('show',function(){
alert('show')
})
找到相应源码
on: function(name, callback, context) {
if (!eventsApi(this, 'on', name, [callback, context]) || !callback) return this;
this._events || (this._events = {});//这是一个事件,将实例中设置一个_events属性
var events = this._events[name] || (this._events[name] = []);//再定义一个events存储this._events[name]
events.push({callback: callback, context: context, ctx: context || this});//事件序列,往数组里push事件
return this;
}
其中有个eventsApi方法,看下这个方法
var eventsApi = function(obj, action, name, rest) {
if (!name) return true;
// Handle event maps.
if (typeof name === 'object') {
for (var key in name) { //遍历object
obj[action].apply(obj, [key, name[key]].concat(rest));//绑定每个事件
}
return false;
}
// Handle space separated event names.
if (eventSplitter.test(name)) {
var names = name.split(eventSplitter);
for (var i = 0, l = names.length; i < l; i++) {//存在字符串中有空格分开,转成数组,遍历数组
obj[action].apply(obj, [names[i]].concat(rest));//绑定每个事件
}
return false;
}
return true;
};
这相当于递归执行绑定事件。
例子中执行了
m.trigger('show');
我们再来看trigger方法
trigger: function(name) {
if (!this._events) return this;//查看_events序列中是否有事件,没有则返回
var args = slice.call(arguments, 1);//闭包调用slice,获取参数,进入triggerEvents方法
if (!eventsApi(this, 'trigger', name, args)) return this;//递归绑定
var events = this._events[name];//从事件序列取出事件,这里同名方法也能取出
var allEvents = this._events.all;//源码将这里写死,也就是说,如果我们定义的方法名是all的,将默认都执行一次
if (events) triggerEvents(events, args);
if (allEvents) triggerEvents(allEvents, arguments);//注意是最后执行
return this;
}
进入triggerEvents方法
var triggerEvents = function(events, args) {//执行方法
var ev, i = -1, l = events.length, a1 = args[0], a2 = args[1], a3 = args[2];
switch (args.length) {//同名方法,按照压进数组的顺序执行,换句话说,先定义的先执行。
case 0: while (++i < l) (ev = events[i]).callback.call(ev.ctx); return;
case 1: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1); return;
case 2: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1, a2); return;
case 3: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1, a2, a3); return;
default: while (++i < l) (ev = events[i]).callback.apply(ev.ctx, args);
}
};
显示结果:

将例子修改一下
var m = new Backbone.Model();
m.on('all',function(){
alert('show-all')
})
m.trigger('show');
因为name是all,所以this._events['all']是绑定事件的,在trigger中的allEvents也会是有值的,既它将执行all的事件。如果你将例子再修改
var m = new Backbone.Model();
m.on('all',function(){
alert('show-all')
})
m.trigger('all');
那它会弹两次alert的。第一次执行events,第二次执行allevents。
关于off,移除事件例子:
var m = new Backbone.Model();
m.on('show',function(){
alert('show')
})
m.off('show')
m.trigger('show');
看一下off方法:
off: function(name, callback, context) {
var retain, ev, events, names, i, l, j, k;
if (!this._events || !eventsApi(this, 'off', name, [callback, context])) return this;
if (!name && !callback && !context) {
this._events = {};
return this;
}
names = name ? [name] : _.keys(this._events);
for (i = 0, l = names.length; i < l; i++) {
name = names[i];
if (events = this._events[name]) {
this._events[name] = retain = [];//清空事件序列
if (callback || context) {
for (j = 0, k = events.length; j < k; j++) {
ev = events[j];
if ((callback && callback !== ev.callback && callback !== ev.callback._callback) ||
(context && context !== ev.context)) {
retain.push(ev);
}
}
}
if (!retain.length) delete this._events[name];//每个事件的话,删除掉事件序列,释放资源
}
}
return this;
}
想一下,this._events中的事件被删除和清空了,我们再调用trigger方法时,肯定是不能触发绑定事件的。
再上一个例子:
var m = new Backbone.Model(); // 将监听函数绑定到m对象的all事件中
m.on('all', function() {
alert('all');
});
// 将监听函数绑定到m对象的自定义事件show中
m.on('show', function() {
alert('show title');
});
// 将另一个监听函数绑定到m对象的自定义事件show中
m.on('show', function() {
alert('show content');
});
// 将监听函数绑定到m对象的自定义事件hide中
m.on('hide', function() {
alert('hide');
}); // 触发m对象的show事件和hide事件
m.trigger('show');
m.trigger('hide');
思考一下,显示结果。

简单来看一下,绑定all事件,因为触发all事件是写在trigger方法中,并且是最后执行,所以调用trigger执行完其他方法后,再执行all事件。每一次调用trigger都会执行一遍。下面就依次绑定show和hide方法,其中show方法绑定了两遍,但方法内容不同,backbone允许这样的绑定。不会覆盖。我们来看一下后台的事件序列中的情况。我们取方法名为show的情况看下

可以看到同名的show方法是两个,trigger执行时,会从数组中依次取出执行,执行顺与定义的顺一致。
内容不多,时间刚好,以上是我的一点读码体会,如有错误,请指出,大家共通学习。
backbone库学习-Events的更多相关文章
- backbone库学习-Router
backbone库的结构http://www.cnblogs.com/nuysoft/archive/2012/03/19/2404274.html 本文的例子来自http://blog.csdn.n ...
- backbone库学习-Collection
backbone库的结构: http://www.cnblogs.com/nuysoft/archive/2012/03/19/2404274.html 本文所有例子来自于http://blog.cs ...
- backbone库学习-model
backbone库的结构: http://www.cnblogs.com/nuysoft/archive/2012/03/19/2404274.html 本文所有例子来自于http://blog.cs ...
- backbone库学习-View
Backbone中的视图提供了一组处理DOM事件.和渲染模型(或集合)数据方法(在使用视图之前,你必须先导入jQuery或Zepto) 视图类提供的方法非常简单,我们一般在backbone.View的 ...
- Backbone.js学习之初识hello-world
说了好久好久要学习Backbone.js,现在终于下定决心开始学习了.然后呢,就根据我的学习进度在这里做个简单的记录,方便新人,也方便我自己以后回忆. 准备 用bower下载这几个库或框架也是醉了.. ...
- 【转】Backbone.js学习笔记(二)细说MVC
文章转自: http://segmentfault.com/a/1190000002666658 对于初学backbone.js的同学可以先参考我这篇文章:Backbone.js学习笔记(一) Bac ...
- Backbone.js学习之Backbone.View(视图)
Backbone.js为复杂WEB应用程序提供模型(models).集合(collections).视图(views)的结构.其中模型用于绑定键值数据和自定义事件:集合附有可枚举函数的丰富API: 视 ...
- muduo网络库学习笔记(三)TimerQueue定时器队列
目录 muduo网络库学习笔记(三)TimerQueue定时器队列 Linux中的时间函数 timerfd简单使用介绍 timerfd示例 muduo中对timerfd的封装 TimerQueue的结 ...
- Libev库学习
Libev库学习 https://www.cnblogs.com/wunaozai/p/3950249.html Libev库学习(1)https://www.cnblogs.com/wunaozai ...
随机推荐
- Android 实用工具Hierarchy Viewer实战
在Android的SDK工具包中,有很多十分有用的工具,可以帮助程序员开发和测试Android应用程序,大大提高其工作效率.其中的一款叫Hierachy Viewer的可视化调试工具,可以很方便地在开 ...
- 通过ReentrantLock源代码分析AbstractQueuedSynchronizer独占模式
1. 重入锁的概念与作用 reentrant 锁意味着什么呢?简单来说,它有一个与获取锁相关的计数器,如果已占有锁的某个线程再次获取锁,那么lock方法中将计数器就加1后就会立刻返回.当释 ...
- 推荐几款API文档集合工具
https://zealdocs.org/ 开源.免费,支持Linux.Windows http://velocity.silverlakesoftware.com/ https://kape ...
- Swift入门篇-基本类型(3)
一:元组 格式 变量或常量关键字 元组变量 = ( 变量,变量, …) 说明: : 元组变量还是一个变量,只不过表现方式和其他变量不一样 :()括号里面可以放入N个变量组成 例子: import Fo ...
- 汇编语言学习笔记(5)——[bx]和loop
1.[bx]代表将bx寄存器中的值作为偏移地址. 2.loop与循环有关 3.inc bx的含义为bx中的内容+1 4.loop指令的格式为: loop 标号 CPU运行loop指令的时候.要进行两步 ...
- 修改nginx服务器类型
通常nginx服务器不隐藏服务器类型及版本信息 curl -I http://www.aaa.com 获取web服务器的类型和版本代码 HTTP/1.1 200 OK Server: ...
- 巧用css border
上下左右边框交界处呈现平滑的斜线.利用这个特点,通过设置不同的上下左右边框宽度或颜色,可以得到小三角.梯形等. 调整宽度大小可以调节三角形形状. 实现三角形 示例1: #test1{ height:2 ...
- BitNami 里有好多开源软件
https://bitnami.com/stacks BitNami 提供wordpress.joomla.drupal.bbpress等开源程序的傻瓜式安装包下载,所有的安装包内置了服务器环境,就是 ...
- 北京地铁月度消费总金额计算(Python版)
最近业余时间在学习Python,这是那天坐地铁时突发奇想,想看看我这一个月的地铁费共多少钱,所以简单的构思了下思路,就直接开写了,没想到用Python来实现还挺简单的. 设计思路: 每次乘车正常消费7 ...
- 高吞吐量的分布式发布订阅消息系统Kafka-- 管理工具 Kafka Manager
一.概述 Kafka在雅虎内部被很多团队使用,媒体团队用它做实时分析流水线,可以处理高达20Gbps(压缩数据)的峰值带宽. 为了简化开发者和服务工程师维护Kafka集群的工作,构建了一个叫做Kafk ...