在Ember 2.0中存储瞬态UI状态的位置

时间:2015-09-16 23:49:42

标签: ember.js

Ember 2.0已经不遗余力地将一切都变成了一个组件。随着可路由的组件即将推出,控制器也可能会逐步淘汰。

上下文

但是,在构建用户界面时我遇到了一个反复出现的问题,到目前为止我还没有令人满意的模式:用户界面状态。

我在做什么?

  • 选择状态
  • 当前焦点
  • 某些树状显示中的折叠/展开状态

基本上,任何不属于实际数据的状态,但必须逐个对象地跟踪。在过去,过去常常使用Controllers作为模型的代理。这种方法现在已经过时了。新方法到处Components为更好。组件执行簿记,跟踪瞬态,然后您可以恢复操作。

我拥有的典型模式是共享状态,例如带有可选项的列表。

问题

构建列表组件,具有以下要求:

  • 可以选择每个项目。
  • 选择状态更改DOM(某些类绑定)。
  • 用户可以在列表组件中绘制一个矩形,一次选择多个项目。
  • 理想情况下,整个行为可以作为mixin抽象出来。

问题:选择标志在哪里?

尝试

1)一切都是一个组成部分。

我将每个项目都设为子组件,比如{{my-list-item}}。该组件跟踪选择状态。问题:列表组件如何更新选择状态?

2)将状态移出子组件。

将它放在列表组件上。在项目列表旁边的单独状态数组中。优点:列表具有所需的所有状态。缺点:在列表中添加或删除项目时保持同步是一场噩梦。这意味着子组件无法访问该状态。或者也许我可以将它作为约束值传递给它们?

3)重新引入代理。

想到它,有一种方法可以分享一些状态:把它放在模型上。好吧,不是在实际模型上,以免污染它们本地状态,而是通过设置一个ArrayProxy来为每个项目返回一些ObjectProxy,以保持状态。

优点:这是我设法完全实现的唯一解决方案。缺点:封装和封装物品是一件麻烦事。此外,经过几层传递后,getset必须通过4个5代理,我担心这会对性能造成影响。

此外,它不适用于mixins。我是否应该抽象出一些HasSelection mixin,HasFoldableItems mixin和Sortable mixin,它们都需要一些状态。

返回绘图板

我找不到更好的模式吗?

我发现了以下相关问题,但这导致我无处可去:

1 个答案:

答案 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'));
    }
  }
});