我正在使用Ember v2.5.1和Ember数据v2.6.2,我有一系列嵌套组件来呈现类别的分层树。最低级别组件categories-tree-node
中有一个关闭操作,它在toggleAddCategory
组件的操作中调用categories-select
函数并传递相关的类别对象。
它在Safari中按预期工作,但由于某种原因,检查状态在Chrome和FF中反转。奇怪的是,当复选框被更改时,值本身的已检查状态绑定会在模板中的其他位置正确呈现。
我创建了demo here,如果您尝试选中/取消选中Chrome / FF vs Safari中的框,您应该会看到问题。是否有一种优先处理这种类型的动作绑定与复选框检查状态的方法?我已经读到使用Observers被认为是Ember 2及以上版本中的反模式,当我尝试这个时它也不适用于子类别。
答案 0 :(得分:0)
好的,所以你的旋律显示Chrome中的状态没有变化,但在Safari中有所改变。
这很可能是Safari中jQuery的一个错误,因为Ember.CheckBox sets checked
使用了jQuery prop方法:
change() {
set(this, 'checked', this.$().prop('checked'));
}
解决方法是将复选框用作尖括号组件(which have one-way bindings by default),以确保checked
组件不会更改input
绑定,而是使用传递在关闭动作中自己手动切换已检查状态。
这也符合Ember推荐的使用Data Down - Actions Up模式从组件设置父属性的最佳实践。
注意:You might want to use the onchange
event rather than onclick
。
儿童 components/categories-tree-node.hbs
<input type="checkbox"
checked={{category.checked}} <!-- checked is just passed from above, not set within the component -->
onchange={{action toggle category}} <!-- onchange calls the passed in action which toggles checked -->
id={{concat elementId '-' category.slug}}
>
...
家长 components/categories-select.js
export default Ember.Component.extend({
// ...
actions: {
toggleAddCategory(category) {
category.toggleProperty('checked'); // toggle the property yourself
// ...
}
}
});
如果您的父操作只执行切换而没有其他操作,您可能不需要它,并且可以使用mut帮助程序在components/categories-tree-node.hbs
内部切换:
<input type="checkbox"
checked={{category.checked}} <!-- checked is just passed from above, not set within the component -->
onchange={{action (mut category.checked) value="target.checked"}} <!-- onchange automatically sets category.checked -->
id={{concat elementId '-' category.slug}}
>