7

我使用更改事件在 Backbone 中发现了一些奇怪的东西。它带有一个具有数组作为属性的模型。如果我让属性在里面推送一个新值并将其设置回模型,则不会触发更改事件......

这是一个完整记录的示例:

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

提前谢谢。

4

2 回答 2

15

hesson 完全正确:

JavaScript 中的数组被视为指针,因此改变数组不会改变指针,也不会触发“change”事件。

但是,作为替代解决方案(如果您还使用 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 fire on model.change()

这将复制对象而不是使其成为引用,但是嵌套对象或数组将只是引用。

于 2013-08-09T03:19:42.403 回答
3

JavaScript 中的数组被视为指针,因此改变数组不会改变指针,也不会触发“change”事件。相反,您需要设置一个方法来改变数组,并在此方法中触发您自己的自定义事件。例如:


mutateArray: function() {
    var numbers = this.get("numbers");
    numbers.push(5);
    this.trigger("mutatedarray");
    return this;
}

请注意,因为 numbers 是一个指针,所以调用 set (没有双关语)是没有意义的,因为 numbers 只是对数组的引用。然后您可以通过监听自定义的 mutatedarray 事件来监听更改,如下所示:


this.on("mutatedarray", this.changedEvent, this);
于 2013-08-09T01:04:44.337 回答