我有一个包含两个对象的父Backbone模型。
(1)一组Backbone模型
(2)一个字符串
如果我绑定到父级,则设置字符串的值会触发change事件,但是对模型数组中某个模型的属性进行调用set不会触发父级的更改事件。
如何修复此问题,以便对数组中任何模型的任何更改都会触发父项更改事件?
编辑 - 按要求添加代码
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
答案 0 :(得分:4)
Backbone模型不会将任何内容与其属性绑定,因此foo
无法知道您正在更改其背后的某个属性。所以,当你这样做时:
foo.set('models', [some_other_model]);
some_other_model.set(...);
你根本没有真正改变foo
,你所做的就是直接改变了foo
的一个属性。模型的属性可以是任何东西,模型只是将它们视为不透明的blob。你会遇到类似的问题:
o = { a: 'b' };
m.set('p', o);
o.a = 'c';
在这两种情况下,您都是通过引用而不是通过模型的界面直接更改模型的属性。
另一方面,收藏品会听取他们模特的事件。集合是模型的集合,因此他们希望其成员成为模型并采取相应的行为。
如果您希望包含的模型传播'change'
事件,那么您必须自己执行此操作,或许覆盖set
以手动绑定更改处理程序以传播事件。您还可以使用内部集合而不是数组来更轻松地传播事件。
您的defaults
中也有一个隐藏的错误。默认值被复制到新模型实例,但副本是浅副本,因此除非使用显式set
替换引用,否则模型最终将共享对数组的相同引用。例如,这个:
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'));
会在控制台中放置两个['pancakes']
,因为m1.get('a')
将返回M.prototype.defaults.a
而不是一个特定于m1
的新空数组:http://jsfiddle.net/ambiguous/AraCu/ < / p>