Backbone源码解析(一):Event模块

时间:2023-01-05 19:22:16

Backbone是一个当下比较流行的MVC框架。它主要分为以下几个模块:
Events, View, Model, Collection, History, Router等几大模块。它强制依赖underscore,jq或者zepto库。通过它,我们可以轻松地来创建单页面应用或者响应式布局界面。它将数据层和界面层抽离,并且使每个View都在自己内部维护自己的业务逻辑,我们更多地去关注单个界面的自身逻辑。以每个模块为例子我们接下来对backbone的设计模式和源代码进行简单的分析。

Events事件模块

首先是Events事件模块,它包含三个方法,分别是bind,unbind和trigger。Events作为全局的一个事件处理模块在后面会分别扩张到各个模块中去,实现每个模块的回掉,触发,解除绑定的事件。

(function() {//创建立即执行函数,建立新环境。
var h = this,
p = h.Backbone,
e;
e = typeof exports !== "undefined" ? exports: h.Backbone = {};
e.VERSION = "0.5.3";//版本信息
var f = h._;//引用underscore.js
if (!f && typeof require !== "undefined") f = require("underscore")._;//如果应用了require.js则采用AMD模块加载方式引用underscore.js
var g = h.jQuery || h.Zepto;//引用jq或者zepto
e.noConflict = function() {//根据API文档,这个方法是返回Backbone的原始值,避免引入多个bk文件,避免冲突。
h.Backbone = p;
return this
};
e.emulateHTTP = !1;
e.emulateJSON = !1;
e.Events = {//事件模块
/*绑定事件,用到其他模块的初始方法中:*/
bind: function(a, b, c) {
var d = this._callbacks || (this._callbacks = {}); (d[a] || (d[a] = [])).push([b, c]);
return this
},
//这个是解除绑定事件不解释
unbind: function(a, b) {
var c;
if (a) {
if (c = this._callbacks) if (b) {
c = c[a];
if (!c) return this;
for (var d = 0,
e = c.length; d < e; d++) if (c[d] && b === c[d][0]) {
c[d] = null;
break
}
} else c[a] = []
} else this._callbacks = {};
return this
},
//事件触发器。它为其他模块的方法提供事件触发功能。比如model的set方法,这里采用的是典型观察模式。在model模块分析中会进行说明。
trigger: function(a) {
var b, c, d, e, f = 2;
if (! (c = this._callbacks)) return this;
for (; f--;) if (b = f ? a: "all", b = c[b]) for (var g = 0,
h = b.length; g < h; g++)(d = b[g]) ? (e = f ? Array.prototype.slice.call(arguments, 1) : arguments, d[0].apply(d[1] || this, e)) : (b.splice(g, 1), g--, h--);
return this
}
};

Events模块虽然会嵌入到其他模块中去,但它是通过扩展的方式extend函数和其他模式关联的,实际上它本质上是一个对象的字面量,通过extend函数扩张到其他类的原型上去。Event的特点首先是有公用的方法,比如bind或者trigger,这些方法可以直接写到其他模块上去,但是会做大量的重复工作。Event模块其实是一个公用的模块,但是,它拥有模块的典型特点,就是它降低了耦合,我们可以从它里面的方法看出,它不直接参与其他模块的逻辑,只关注自己内部实现,正是因为这个特点,它才能适配到各个模块上去做它的工作。下图展示的就是它如何被扩展到其他模块上去的:

源码:

Backbone源码解析(一):Event模块

那么Events扩展到那些模块之中干了些什么事情呢,我们可以举几个例子,形象地说明一下:

项目代码:

Backbone源码解析(一):Event模块

我们这里实例化一个View类,在初始化函数中就是用到了bind方法,实际上,此时的bind方法以及属于Model了(this.model指向某个Model实例,在之前我们已经给View的model属性复制了)。它把一个change事件添加带私有变量_callbakc中去,等待model的change事件触发后,它就会触发View的render的事件,即model改变使得视图重新渲染。这样就实现了bk框架的最基本思想,模型驱动视图。

项目代码:

Backbone源码解析(一):Event模块

上面的代码也是异曲同工。

由于backbone的模块之间存在着很多联系,事实上把一个个模块分开来讲是不全面地的,或多或少,在谈到一个地方的时候要牵扯到一大堆其他的地方,就像一层层的纵横交错的高架桥一样,彼此独立又彼此关联。所以建议你关注后续的代码分析,最后全面地理解bk框架的工作原理。