您的位置:首页 > 其它

Backbone事件Events

2015-11-28 20:42 387 查看
说道Backbone的事件机制。自己也是逗逼了。敲了一遍Backbone的源码。。居然是还不知道他的机制。。

先上Events On对象的源码

/**
* Created by More on 2015/11/28.
*/
var Events = Backbone.Events ={
/**
* params:
* events : 事件们
* callback : 回调函数
* context : 上下文,俗称的this
*
* **/
on: function(events,callback,context){
var calls,//回调函数数字
event,//切割的事件名称
node,//节点对象
tail,//节点的结尾,用于判断所有回调是否执行完毕
list;//保存当前对象中的事件对象

if(!callback){
return this;
}

//事件切割数组
events = events.split(eventSplitter);

//回调对象
calls = this._callbacks || (this._callbacks = {});

while(event = events.shift()){
list = calls[event];

node = list ? list.tail : {};

node.next = tail = {};
node.context = context;

calls[event] ={
tail : tail,
next : list ? list.next : node
}

}
return this;
}
}

一开始,我都不知道原理是啥,只知道他丢进去了一个_CallBacks对象在Backbone里边,里边的键值对是有序的,包括回调函数都是有序的保存在该对象中,但是不知道是怎么触发的。。

老老实实又去看了下collection的原型,再上源码

add : function(models, options) {

// 局部变量定义

var i, index, length, model, cid, id, cids = {}, ids = {}, dups = [];

options || ( options = {});

// models必须是一个数组, 如果只传入了一个模型, 则将其转换为数组

models = _.isArray(models) ? models.slice() : [models];

// 遍历需要添加的模型列表, 遍历过程中, 将执行以下操作:

// - 将数据对象转化模型对象

// - 建立模型与集合之间的引用

// - 记录无效和重复的模型, 并在后面进行过滤

for( i = 0, length = models.length; i < length; i++) {

// 将数据对象转换为模型对象, 简历模型与集合的引用, 并存储到model(同时models中对应的模型已经被替换为模型对象)

if(!( model = models[i] = this._prepareModel(models[i], options))) {

throw new Error("Can't add an invalid model to a collection");

}

// 当前模型的cid和id

cid = model.cid;

id = model.id;

// dups数组中记录了无效或重复的模型索引(models数组中的索引), 并在下一步进行过滤删除

// 如果cids, ids变量中已经存在了该模型的索引, 则认为是同一个模型在传入的models数组中声明了多次

// 如果_byCid, _byId对象中已经存在了该模型的索引, 则认为同一个模型在当前集合中已经存在

// 对于上述两种情况, 将模型的索引记录到dups进行过滤删除

if(cids[cid] || this._byCid[cid] || ((id != null) && (ids[id] || this._byId[id]))) {

dups.push(i);

continue;

}

// 将models中已经遍历过的模型记录下来, 用于在下一次循环时进行重复检查

cids[cid] = ids[id] = model;

}

// 从models中删除无效或重复的模型, 保留目前集合中真正需要添加的模型列表

i = dups.length;

while(i--) {

models.splice(dups[i], 1);

}

// 遍历需要添加的模型, 监听模型事件并记录_byCid, _byId列表, 用于在调用get和getByCid方法时作为索引

for( i = 0, length = models.length; i < length; i++) {

// 监听模型中的所有事件, 并执行_onModelEvent方法

// _onModelEvent方法中会对模型抛出的add, remove, destroy和change事件进行处理, 以便模型与集合中的状态保持同步

( model = models[i]).on('all', this._onModelEvent, this);

// 将模型根据cid记录到_byCid对象, 便于根据cid进行查找

this._byCid[model.cid] = model;

// 将模型根据id记录到_byId对象, 便于根据id进行查找

if(model.id != null)

this._byId[model.id] = model;

}

// 改变集合的length属性, length属性记录了当前集合中模型的数量

this.length += length;

// 设置新模型列表插入到集合中的位置, 如果在options中设置了at参数, 则在集合的at位置插入

// 默认将插入到集合的末尾

// 如果设置了comparator自定义排序方法, 则设置at后还将按照comparator中的方法进行排序, 因此最终的顺序可能并非在at指定的位置

index = options.at != null ? options.at : this.models.length;

splice.apply(this.models, [index, 0].concat(models));

// 如果设置了comparator方法, 则将数据按照comparator中的算法进行排序

// 自动排序使用silent属性阻止触发reset事件

if(this.comparator)

this.sort({

silent : true

});

// 依次对每个模型对象触发"add"事件, 如果设置了silent属性, 则阻止事件触发

if(options.silent)

return this;

// 遍历新增加的模型列表

for( i = 0, length = this.models.length; i < length; i++) {

if(!cids[( model = this.models[i]).cid])

continue;

options.index = i;

// 触发模型的"add"事件, 因为集合监听了模型的"all"事件, 因此在_onModelEvent方法中, 集合也将触发"add"事件

// 详细信息可参考Collection.prototype._onModelEvent方法

model.trigger('add', model, this, options);

}

return this;

},

原来在这里的最后几行代码中,手动触发了这个事件,导致自定义的事件可以被触发。。差点就被自己给坑进去了。。还以为自己发现了什么心技能。。可以隐式的定义方法在对象的_callBacks对象中。。

呀呀呀。。继续干。。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: