emberjs 双向绑定在初始化赋值后暂时中断

emberjs two-way-binding temporarily broken after value assignment at init

我正尝试在 init 生命周期挂钩处为我的组件之一分配默认值;如果未定义的值从父组件传递。最初一切似乎都按预期工作;但是,当我的组件被迫重新渲染时(可能通过父组件的另一个 属性 值更新);父组件的未定义值写回我的组件。

这意味着;我在初始化时赋值并没有反映到父组件,也就是说双向绑定暂时不起作用(父子组件的值不同步)。这是预期的行为还是我错过了某事。初始化事件重要吗?初始化组件未定义值的合适位置在哪里?请参阅 twiddle 以获取简单说明。

好的,第一个解决方法是在 attr 上使用 update 函数。签出 this twiddle.

我在 .js 中将 this.set('name', 'tom') 替换为 this.attrs.name.update('tom'),在 .hbs 中将 {{name}} 替换为 {{attrs.name}}

另一种解决方法是将赋值包装在 Ember.run.later 中,就像我所做的那样 here,我将 this.set('name', 'tom') 替换为:

Ember.run.later(() => {
  this.set('name', 'tom');
});

这就是解决方法。

绑定未完全在 init 上设置的事实由来已久。但通常它是一种反模式,可以在子组件中初始化一个值并将该值提供给父组件。它使您的代码可读性降低,并且再次违反 DDAU(数据下降,操作上升)原则。

我建议在创建模型时显式初始化数据,而不是在组件评估周期中隐式初始化。

对于您不想存储的默认值,我建议您编写一个计算 属性:

nameWithDefault: computed('name', {
    get() {
        return get(this, 'name') || 'tom';
    },
    set(key, val) {
        set(this, 'name', val);
    }
})

这是显式的,不会在查看组件后记下数据,并为用户工作。

我同意 Lux 的解决方案,但如果您想尝试其他方法,也许您可​​以在 child 组件上添加一个计算的 属性 来检查名称或默认为另一个字符串。这允许您在不同的 child 模板上使用不同的默认值(假设您有不同的 child 组件使用相同的 name 属性)。

child-component.js

export default Ember.Component.extend({
  child_name: Ember.computed('name', function() {
    return this.get('name') || 'tom';
  }),
});

child-component.hbs

{{child_name}}
<br>
{{surname}}