Ember.js 余烬组件的所有实例共享变量的最佳方式是什么?

Ember.js 余烬组件的所有实例共享变量的最佳方式是什么?,ember.js,ember-components,Ember.js,Ember Components,我有一个余烬组件,它本质上是一个面板。一个页面上可以有多个此面板的实例,但在任何给定时间只能有一个实例处于“活动”状态。组件的每个实例都必须知道是否有任何其他面板变为“活动”,以便它们可以删除其“活动”状态。我真的不希望移动JavaScript使父组件发生这种情况。相反,我希望将其保留在这个组件中。在Angular中,我使用静态变量来实现这一点。在余烬中最好的方法是什么 我真的不希望移动JavaScript来让这发生在 父组件 是否要避免父组件处理与面板“活动”相关的任何内容?若有,原因为何?*

我有一个余烬组件,它本质上是一个面板。一个页面上可以有多个此面板的实例,但在任何给定时间只能有一个实例处于“活动”状态。组件的每个实例都必须知道是否有任何其他面板变为“活动”,以便它们可以删除其“活动”状态。我真的不希望移动JavaScript使父组件发生这种情况。相反,我希望将其保留在这个组件中。在Angular中,我使用静态变量来实现这一点。在余烬中最好的方法是什么

我真的不希望移动JavaScript来让这发生在 父组件

是否要避免父组件处理与面板“活动”相关的任何内容?若有,原因为何?*若否:

Ember会自动为每个组件的标记(除非它是无标记组件)提供一个id,该id可以从js代码中访问。您可以在父组件上创建属性
activePanelId
,并将其传递给所有面板:
{{pa nel activePanelId=activePanelId}}
,然后签入每个面板

{{#if (eq elementId activePanelId)}}
  {{!whatever is different on the active panel}}
{{/if}}
或者在js代码中使用它:

isActive: Ember.computed('activePanelId', function() {
    return this.get('activePanelId')===this.get('elementId');
},
如果面板通过与自身相关的操作(例如单击它)变为活动状态,只需在相应操作中将
activePanelId
设置为
elementId
——因为属性
activePanelId
在父组件上只存在一次,所以它传递到的所有其他面板都会注意

如果使用
elementId
感觉有点不对劲,那么最好给每个面板指定一个不同的名称,并将
activePanelName
存储在调用组件中


*如果您真的不想在父组件中使用该属性,您可以将其移动到服务中,然后将其注入面板组件中,但我还无法想象有什么好的理由更愿意使用该属性。

@arne.b的anwser对其进行了很好的总结,这是使用公共父数据处理组件状态的最佳方法,但是,如果您对不使用父组件非常认真,那么有一种方法可以完成它

例如:

import Ember from 'ember';

export default Ember.Component.extend({
   sharedObject: {},
   sharedArray: [],
});
在上述组件中,您可以使用
sharedObject
sharedArray
与组件的多个实例交换状态。对象或数组中的任何更改都将反映到同一组件的所有实例中


示例。

如何使用上下文组件?余烬文档-因此您可以拥有面板标题并使用组件helper@rossjha我从来没有用过这些(而且我很难在晚上这么晚的时候把头裹在它们身上;-)。请随意根据它写一个答案——我很想看看它是如何工作的。这不是一个好的方法,因为它改变了组件原型。一个意外的副作用是,组件原型的更改将在整个集成测试中保持不变。这可能会导致以后的测试从您不打算使用的数据开始,并可能导致各种难以跟踪的故障。如果您不想创建父组件,更好的方法是创建一个服务(默认情况下是单例),并将其注入到您想要共享状态的任何组件中。