我知道这是违反数据下行动的想法,但是,跟着它,我的父组件看起来非常人满为患。
所以,我在寻找是否还有另一种方式。
示例案例: 我有一个父组件,包含“过滤器”,“表格”和“选项”。现在,当用户从选项中选择另一个表时,必须重置过滤器。 因此,我需要从父组件触发重置过滤器。
答案 0 :(得分:1)
您可以将父组件属性绑定到子组件,并且您可以通过组件钩子在没有观察者的情况下对父组件属性更改做出反应。 这将遵循Data Down Actions Up(DDAU)原则并避免观察者。
在下面的例子中,
只要在父组件中更改selectedOptionId
,那么在子组件(my-table)中将通过按顺序调用以下挂钩(didUpdateAttrs
,didReceiveAttrs
,willUpdate
来开始重新渲染, willRender
,didUpdate
,didRender
)。您将从didUpdateAttrs和didReceiveAttrs钩子中获取newAttrs
参数的oldAttrs
和options
属性。
首次渲染时,didReceiveAttrs钩子中不会有options.oldAttrs
。
<强>模板/ application.hbs 强>
{{parent-component }}
{{outlet}}
<强>模板/组件/父 - component.hbs 强>
{{my-table selectedOptionId=selectedOptionId}}
<button {{action 'changeOption'}}> Change Option </button>
{{yield}}
**组件/父 - component.js
import Ember from 'ember';
export default Ember.Component.extend({
selectedOptionId:1,
actions:{
changeOption(){
this.set('selectedOptionId',2);
}
}
});
<强>模板/组件/我的-table.hbs 强>
{{selectedOptionId}}
{{yield}}
<强>组件/我的-table.js 强>
import Ember from 'ember';
export default Ember.Component.extend({
didReceiveAttrs(options){
this._super(...arguments);
//this will run both initial render and rerender.
//For initial rendering alone options.oldAttrs will not be available
},
didUpdateAttrs(options){
this._super(...arguments);
//this will run only for the rerender
if(options.oldAttrs.selectedOptionId.value !== options.newAttrs.selectedOptionId.value) {
this.send('triggerOptionChangeEvent');
}
},
actions:{
triggerOptionChangeEvent(){
console.log('triggerOptionChangeEvent ',this.get('selectedOptionId'));
}
}
});
<强>更新强> 来自ember guides,
注意:新的Ember开发人员经常过度使用观察者。观察者在Ember框架本身中大量使用,但对于Ember app开发人员面临的大多数问题,计算属性是合适的解决方案。
所以总是远离使用观察者。我们甚至不应该在生命周期钩子方法中使用options
。这是deprecated。所以我们应该手动查找特定属性是否已更改。这是正确的方法。请参阅this RFC for more details。它包含正确的方法,以避免使用opions
中的didReceiveAttrs
属性。
请参阅stefan penner excellant talk以在不使用观察者的情况下解决问题。