// When you have more items than you want to add or remove individually, // 当你有更多数据要逐个添加或者删除 // you can reset the entire set with a new list of models, without firing // 你可以重置这个实例设置一个新的models列表,不用触发任何add和remove的事件 // any granular `add` or `remove` events. Fires `reset` when finished. // 添加删除完毕后触发reset事件 // Useful for bulk operations and optimizations. // 对批量操作和优化来说非常有用 reset: function(models, options) { //options存在则深拷贝一份,或设置为{} options = options ? _.clone(options) : {}; //遍历models,切断模型和某个集合的关系。 for (var i = 0; i < this.models.length; i++) { this._removeReference(this.models[i], options); } //将options的previousModels指向这个models options.previousModels = this.models; //初始化实例的length,models和_byId属性 ->此时this.models=[]; this._reset(); //调用add方法添加models到Collection models = this.add(models, _.extend({silent: true}, options)); //如果options设置了silent=false,手动触发reset事件进行重置 if (!options.silent) this.trigger('reset', this, options); return models; },
add: function(models, options) { return this.set(models, _.extend({merge: false}, options, addOptions)); } ... // Update a collection by `set`-ing a new list of models, adding new ones, // removing models that are no longer present, and merging models that // already exist in the collection, as necessary. Similar to **Model#set**, // the core operation for updating the data contained by the collection. set: function(models, options) { //models为空直接返回false跳出函数 if (models == null) return;
// 设置at 如果指定了at,那么排序就无意义 // 如果at不为空强制转为数字(正常范围内) // 如果at大于数组长度: 设为数组长度 // 如果at小余0:反向设置索引 var at = options.at; if (at != null) at = +at; if (at > this.length) at = this.length; if (at < 0) at += this.length + 1;
// 准备要放数据的设置,添加,合并,移除和modelMap的空数组 var set = []; var toAdd = []; var toMerge = []; var toRemove = []; var modelMap = {};
// 为各个数据设置引用 var add = options.add; var merge = options.merge; var remove = options.remove;
// 设置排序状态,是否可以排序和排序属性 var sort = false; var sortable = this.comparator && at == null && options.sort !== false; var sortAttr = _.isString(this.comparator) ? this.comparator : null;
// Turn bare objects into model references, and prevent invalid models // from being added. // 将纯对象变成model引用,防止无效的models被加进来。 var model, i; for (i = 0; i < models.length; i++) { model = models[i];
// If a duplicate is found, prevent it from being added and // optionally merge it into the existing model. // 如果一个副本已存在,防止被加进来,可选是否合并它到已存在的model var existing = this.get(model); //获取已经存在的model数组 if (existing) { // 如果存在,判断options.merge是否存在&&option的merge是否没有加入过 // 如果是 处理数据压入到toMerge if (merge && model !== existing) { var attrs = this._isModel(model) ? model.attributes : model; if (options.parse) attrs = existing.parse(attrs, options); existing.set(attrs, options); toMerge.push(existing); if (sortable && !sort) sort = existing.hasChanged(sortAttr); } // 如果存在且modelMap中没有这个cid // 那么设置modelMap对应的cid属性值为true,压入existing到set数组 if (!modelMap[existing.cid]) { modelMap[existing.cid] = true; set.push(existing); }
// models[i]设为处理后的existing models[i] = existing;
// If this is a new, valid model, push it to the `toAdd` list. // 如果是一个新的有效的model,将它压入到toAdd数组 } else if (add) { model = models[i] = this._prepareModel(model, options); if (model) { toAdd.push(model); this._addReference(model, options); modelMap[model.cid] = true; set.push(model); } } }
// Remove stale models. // 移除过期的models if (remove) { for (i = 0; i < this.length; i++) { model = this.models[i]; if (!modelMap[model.cid]) toRemove.push(model); } if (toRemove.length) this._removeModels(toRemove, options); }
// See if sorting is needed, update `length` and splice in new models. // 判断是否需要排序,更新length并切片到新的models列表 var orderChanged = false; var replace = !sortable && add && remove; if (set.length && replace) { orderChanged = this.length !== set.length || _.some(this.models, function(m, index) { return m !== set[index]; }); this.models.length = 0; splice(this.models, set, 0); this.length = this.models.length; } else if (toAdd.length) { if (sortable) sort = true; //如果at存在插入到at后面 不然插入到最后 splice(this.models, toAdd, at == null ? this.length : at); this.length = this.models.length; }
// Silently sort the collection if appropriate. // 静默排序 if (sort) this.sort({silent: true});
// Unless silenced, it's time to fire all appropriate add/sort/update events. // 除非设置了sliencd,是时候去触发所有的添加删除排序更新操作 if (!options.silent) { for (i = 0; i < toAdd.length; i++) { if (at != null) options.index = at + i; model = toAdd[i]; model.trigger('add', model, this, options); } if (sort || orderChanged) this.trigger('sort', this, options); if (toAdd.length || toRemove.length || toMerge.length) { options.changes = { added: toAdd, removed: toRemove, merged: toMerge }; this.trigger('update', this, options); } }
// Return the added (or merged) model (or models). return singular ? models[0] : models; },