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}}
我正尝试在 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}}