Ember 2.0已经不遗余力地将一切都变成了一个组件。随着可路由的组件即将推出,控制器也可能会逐步淘汰。
上下文
但是,在构建用户界面时我遇到了一个反复出现的问题,到目前为止我还没有令人满意的模式:用户界面状态。
我在做什么?
基本上,任何不属于实际数据的状态,但必须逐个对象地跟踪。在过去,过去常常使用Controllers
作为模型的代理。这种方法现在已经过时了。新方法到处Components
为更好。组件执行簿记,跟踪瞬态,然后您可以恢复操作。
我拥有的典型模式是共享状态,例如带有可选项的列表。
问题
构建列表组件,具有以下要求:
问题:选择标志在哪里?
尝试
1)一切都是一个组成部分。
我将每个项目都设为子组件,比如{{my-list-item}}。该组件跟踪选择状态。问题:列表组件如何更新选择状态?
2)将状态移出子组件。
将它放在列表组件上。在项目列表旁边的单独状态数组中。优点:列表具有所需的所有状态。缺点:在列表中添加或删除项目时保持同步是一场噩梦。这意味着子组件无法访问该状态。或者也许我可以将它作为约束值传递给它们?
3)重新引入代理。
想到它,有一种方法可以分享一些状态:把它放在模型上。好吧,不是在实际模型上,以免污染它们本地状态,而是通过设置一个ArrayProxy来为每个项目返回一些ObjectProxy
,以保持状态。
优点:这是我设法完全实现的唯一解决方案。缺点:封装和封装物品是一件麻烦事。此外,经过几层传递后,get
和set
必须通过4个5代理,我担心这会对性能造成影响。
此外,它不适用于mixins。我是否应该抽象出一些HasSelection
mixin,HasFoldableItems
mixin和Sortable
mixin,它们都需要一些状态。
返回绘图板
我找不到更好的模式吗?
我发现了以下相关问题,但这导致我无处可去:
答案 0 :(得分:8)
很棒的问题 - 我实际上去了其中一个核心的ember团队成员找出答案,目前答案是服务。因为组件最好是无状态的(大多数情况下),所以可以利用服务来保持这种不适合服务器持久化模型的状态。
这是一个很好的例子,Stef Penner汇总了你如何在你的余烬应用中保存“电子邮件草稿”(不是持久的后端)
https://github.com/stefanpenner/ember-state-services
供参考的示例组件(来自上面的github项目)
export default Ember.Component.extend({
tagName: 'form',
editEmailService: Ember.inject.service('email-edit'),
state: Ember.computed('email', function() {
return this.editEmailService.stateFor(this.get('email'));
}).readOnly(),
actions: {
save() {
this.get('state').applyChanges();
this.sendAction('on-save', this.get('email'));
},
cancel() {
this.get('state').discardChanges();
this.sendAction('on-cancel', this.get('email'));
}
}
});