简体   繁体   English

Backbone.js-模型数组的Change事件不会在元素更改时触发

[英]Backbone.js - Change Event on Array of Models Doesn't Trigger On Element Change

I have a parent Backbone Model that contains two objects. 我有一个包含两个对象的父骨干模型。

(1) An array of Backbone Models (1)骨干模型数组

(2) A string (2)字符串

If I bind to the parent, setting the value of the string does trigger the change event, however calling set on an attribute of one of the models in the array of models does not trigger the change event on the parent. 如果我绑定到父对象,则设置字符串的值会触发更改事件,但是,在模型数组中的一个模型的属性上调用set不会触发父对象的更改事件。

How do I fix this so that any change to any of the models in the array triggers the parents change event? 如何解决此问题,以便对阵列中的任何模型进行任何更改都会触发父级更改事件?

EDIT -- Added Code by request 编辑-根据要求添加代码

var myModel = Backbone.Model.extend(
  {
    defaults : {
      models : [],
      aString: 'foobar'
    }
  }
);
var foo = new myModel();
var arrayElement = Backbone.Model.extend({x: 7});
var arrayElement1 = new arrayElement({x: 7});
foo.set('models', [arrayElement1]);
foo.bind('change', function() { console.log('changed!')});
arrayElement1.set('x', 10);  //Does not trigger console log
foo.set('aString', 'barfoo'); //Does trigger console log

Backbone models don't bind anything to their attributes so foo has no way of knowing that you are changing one of its attributes behind its back. 骨干模型不会将任何内容绑定到其属性,因此foo无法知道您正在更改其背后的属性之一。 So, when you do this: 因此,当您这样做时:

foo.set('models', [some_other_model]);
some_other_model.set(...);

you haven't actually changed foo at all, all you've done is changed one of foo 's attributes directly. 您实际上根本没有更改foo ,您所做的全部操作都是直接更改foo的属性之一。 A model's attributes can be anything, the model simply treats them as opaque blobs. 模型的属性可以是任何东西,模型只是将它们视为不透明的斑点。 You'll have similar problems with something like this: 您将遇到类似的类似问题:

o = { a: 'b' };
m.set('p', o);
o.a = 'c';

In both cases, you're directly changing a model's attribute through a reference rather than through the model's interface. 在这两种情况下,您都是通过引用而不是通过模型的界面直接更改模型的属性。

Collections, on the other hand, do listen for events on their models. 另一方面,集合确实在其模型上监听事件。 Collections are collections of models so they expect their members to be models and behave accordingly. 集合是模型的集合,因此他们希望其成员成为模型并相应地表现。

If you want a contained model to propagate 'change' events then you'll have to do it yourself by, perhaps, overriding set to manually bind change handlers to propagate the events. 如果您希望包含的模型传播'change'事件,那么您可能必须自己做,也许是通过覆盖set以手动绑定变更处理程序来传播事件。 You could also use an internal collection instead of an array to make propagating the events easier. 您也可以使用内部集合而不是数组来简化事件的传播。


You also have a hidden bug in your defaults . 您的defaults也有一个隐藏的错误。 The defaults are copied to new model instances but the copy is a shallow copy so your models will end up sharing the same reference to the array unless an explicit set is done to replace the reference. 默认值将被复制到新的模型实例,但是副本是浅表副本,因此您的模型最终将共享对数组的相同引用,除非完成显式set来替换引用。 For example, this: 例如,这:

var M = Backbone.Model.extend({
    defaults: {
      a: []
    }
});
var m1 = new M();
m1.get('a').push('pancakes');
console.log(M.prototype.defaults.a);
var m2 = new M();
console.log(m2.get('a'));

will put two ['pancakes'] in the console because m1.get('a') will return M.prototype.defaults.a rather than a new empty array that is specific to m1 : http://jsfiddle.net/ambiguous/AraCu/ 将在控制台中放置两个['pancakes'] ,因为m1.get('a')将返回M.prototype.defaults.a而不是特定于m1的新的空数组: http : //jsfiddle.net/ambiguous / AraCu /

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM