在Ember.js中,创建一个对子属性变化做出反应的观察者会导致非直观的行为。如果观察者直接观察数组属性,则它无法触发,而如果它观察到对同一属性的绑定,则它按预期工作。
一个简单的例子:
车把:
<script type="text/x-handlebars">
<b>App.View1.name:</b> {{App.View1.name}} <br />
<b>App.View2.name:</b> {{App.View2.name}}
</script>
的Javascript:
App = Em.Application.create();
// A common dependency for two views
var dependency = Em.Object.create({
prop: []
});
// Directly observes dependency.prop
App.View1 = Em.View.create({
dependency: dependency,
name: "Foo",
changeName: function () {
this.set("name", "Bar");
}.observes("dependency.prop")
});
// Indirectly observes dependency.prop via a binding
App.View2 = Em.View.create({
dependency: dependency,
name: "Foo",
changeName: function () {
this.set("name", "Bar");
}.observes("prop"),
propBinding: "dependency.prop"
});
// Updating the 'prop' property of dependency with an element.
dependency.get("prop").pushObject("An object.");
我在这里把它放在JSFiddle上:http://jsfiddle.net/kbaXG/50/
此处,App.View1.name
未更新(保持“Foo”)而App.View2.name
更新(“Bar”)。
这是预期的行为,是否正在创建绑定可接受的解决方法?
答案 0 :(得分:2)
Bindings是Ember.js中的一个基本概念,所以不要犹豫使用它:)
如果您为dependency
创建绑定,则您的示例有效,请参阅http://jsfiddle.net/pangratz666/Gqc7Q/:
App = Em.Application.create({
VERSION: "0.1"
});
App.dependency = Em.Object.create({
prop: []
});
App.View1 = Em.View.create({
dependencyBinding: 'App.dependency',
name: "Foo",
changeName: function () {
this.set("name", "Bar");
}.observes("dependency.prop")
});
App.View2 = Em.View.create({
dependencyBinding: 'App.dependency',
name: "Foo",
changeName: function () {
this.set("name", "Bar");
}.observes("prop"),
propBinding: "dependency.prop"
});
// Updating the 'prop' property of dependency.
dependency.get("prop").pushObject("An object.");
<强>更新强>
问题在于您正在更改数组的内容而不是数组本身。因此,您必须将观察者路径更改为dependency.prop.@each
,请参阅http://jsfiddle.net/pangratz666/3QccA/。但我不知道为什么它使用绑定方法而不是这个...你应该在GitHub上提交一张票。
作为最后一点,使用绑定的上述解决方案是更像Ember的方法......
var dependency = Em.Object.create({
prop: []
});
App.View1 = Em.View.create({
dependency: dependency,
name: "Foo",
changeName: function () {
this.set("name", "Bar");
}.observes("dependency.prop.@each")
});
App.View2 = Em.View.create({
dependency: dependency,
name: "Foo",
changeName: function () {
this.set("name", "Bar");
}.observes("prop"),
propBinding: "dependency.prop.@each"
});
// Updating the 'prop' property of dependency.
dependency.get("prop").pushObject("An object.");