如何在Ember对象中观察嵌入式数组?

时间:2012-05-22 09:20:59

标签: ember.js

在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”)。

这是预期的行为,是否正在创建绑定可接受的解决方法?

1 个答案:

答案 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.");