我在Backbone中使用更改事件发现了一些奇怪的东西。 这是一个模型,它有一个数组作为属性。 如果我让属性在内部推送一个新值并将其设置回模型,则不会触发change事件...
以下是一个完整记录的示例:
var TestModel = Backbone.Model.extend({
defaults : {
numbers : []
},
initialize : function() {
this.on('change:numbers', this.changedEvent);
},
changedEvent : function() {
console.log('model has changed');
}
});
var oTestModel = new TestModel();
oTestModel.set('numbers', [2, 3, 4]); // change:numbers Event is fired
var aNumbers = oTestModel.get('numbers');
aNumbers.push(5);
oTestModel.set('numbers', aNumbers); // change:numbers event is NOT fired BUT WHY???
// oTestModel.set('numbers', [2, 3, 4]);
// If this line is not commented out change:numbers event is also fired
console.log(oTestModel.toJSON()); // Dumps out [2,3,4,5] Respective [2,3,4] if line above is not commented out
提前谢谢。
答案 0 :(得分:15)
hesson绝对正确:
JavaScript中的数组被视为指针,因此改变数组不会改变指针,也不会触发“更改”事件。
但是,作为替代解决方案(如果您还使用underscore.js),您可以这样做:
var aNumbers = _.clone(oTestModel.get('numbers'));
aNumbers.push(5);
oTestModel.set('numbers', aNumbers); //Will trigger the changed:numbers event
从这个类似问题的答案中可以看出: Backbone.js : change not firing on model.change()
这将复制对象而不是使其成为引用,但嵌套对象或数组将只是引用。
答案 1 :(得分:3)
JavaScript中的数组被视为指针,因此改变数组不会改变指针,也不会触发“更改”事件。相反,您需要设置一个方法来改变数组,并在此方法中触发您自己的自定义事件。例如:
mutateArray: function() {
var numbers = this.get("numbers");
numbers.push(5);
this.trigger("mutatedarray");
return this;
}
请注意,因为数字是一个指针,所以调用set(没有双关语)是没有意义的,因为数字只是对数组的引用。然后你可以通过听这样的自定义mutatedarray事件来听取变化:
this.on("mutatedarray", this.changedEvent, this);