如何控制 ember 组件观察者的执行顺序?

How do I control ember component observer execution order?

我有一个组件中的一个组件。 child 组件通过模板有两个属性 passed-in。这些属性在 child 的 component.js.

中都有单独的观察者

当我以特定顺序更新 parent 组件中的绑定属性时,child 组件的观察器以错误的顺序触发。

如何控制观察者在 child 组件中开火的顺序?

My specific case.

It's been pointed out to me that observers shouldn't be necessary anymore. But they still exist in ember 2.0 so there must be use for them yet. I'll explain my situation anyhow and hopefully the wiser of you out there can let me know how to accomplish this without observers.

In my case, the parent component is a menu for a game, containing many submenus. To switch between each submenu, I use a slide animation so the current menu disappears off screen and the new menu enters swapping the two animating menus in and out as needed. This is accomplished in a side-switcher component (the child in this case).

The parent menu contains tabs which when clicked, need to communicate to the child side-switcher component which submenu should now be shown, and which direction to slide (the two properties). The direction needs to be set first, then the submenu since when the submenu changes, that's what triggers the actual animation. Ember 2.0 philosophy states actions cannot go down, but data (properties) can, so observing properties is the road I'm going down.

Note, in my use case it's actually only the menu property which gets observed, but while debugging this, I had to observe the direction property as well, since my menus were sliding the wrong way all over the place.

The direction needs to be set first, then the submenu since when the submenu changes, that's what triggers the actual animation. Ember 2.0 philosophy states actions cannot go down, but data (properties) can, so observing properties is the road I'm going down.

我认为你可以通过使用 didInitAttrsdidReceiveAttrs 钩子来摆脱观察者。这些钩子有助于一起处理属性,而无需考虑顺序。详情:http://emberjs.com/blog/2015/06/12/ember-1-13-0-released.html#toc_component-lifecycle-hooks

让子组件有属性directionsubmenu.

//parent component template
{{child-component direction=direction submenu=submenu}}

您可以通过 getAttr 获取属性并根据需要进行处理:

// child component
direction: defaultValue,
submenu: defaultValue,

didReceiveAttrs() {
 // your logic 
 this.set('direction', this.getAttr('direction') || defaultDir);
 this.set('submenu', this.getAttr('submenu') || defaultSumbenu);
}

警告:现在 ember 指南和文档缺少对生命周期挂钩的解释。可以建议查看 ember-collection addon code 作为工作示例。

感谢 Artych,实际上是 didUpdateAttrs 钩子解决了我的问题,因为我需要能够对其中一个属性的所有更改做出反应,与初始化分开。

给定这样消耗的组件:

{{my-component myAttr=changeableAttr myOtherAttr=otherAttr}}

在component.js:

didUpdateAttrs(options){

    if( options.newAttrs.myAttr !== options.oldAttrs.myAttr ){

      // React to changes outside the component

    }

},

在任何给定的 运行 循环中的所有属性更改后都会触发此事件,并允许您以您喜欢的任何顺序在组件内进行处理。

这也回答了如何为我向组件发送操作的问题,或者更准确地说,如何让组件对外部变化做出反应的问题。

为了完整起见,我确实弄清楚了如何更改触发观察者的顺序:这只是它们在模板中的组件上定义的顺序。依赖于此是非常糟糕的设计,因此有更好的解决方案 didUpdateAttrsdidReceiveAttrs.

是有道理的