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

Ember.js 在Ember 2.0中存储瞬态UI状态的位置,ember.js,Ember.js,余烬2.0已经尽了很大的努力使一切成为一个组件。随着可路由组件即将推出,控制器也可能会逐步淘汰 上下文 然而,在构建用户界面时,我面临一个反复出现的问题,到目前为止,我还没有一个令人满意的模式:用户界面状态 我在说什么 选择状态 当前焦点 某些树显示中的折叠/展开状态 基本上,任何不属于实际数据一部分的状态都必须逐个对象进行跟踪。在过去,这通常是通过充当模型代理的控制器来完成的。这种方法现在已经过时了。新的方法是组件无处不在,这样会更好。组件进行簿记,跟踪瞬态,然后返回操作 不过,我拥有的一

余烬2.0已经尽了很大的努力使一切成为一个组件。随着可路由组件即将推出,控制器也可能会逐步淘汰

上下文

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

我在说什么

  • 选择状态
  • 当前焦点
  • 某些树显示中的折叠/展开状态
基本上,任何不属于实际数据一部分的状态都必须逐个对象进行跟踪。在过去,这通常是通过充当模型代理的
控制器来完成的。这种方法现在已经过时了。新的方法是
组件
无处不在,这样会更好。组件进行簿记,跟踪瞬态,然后返回操作

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

问题

根据以下要求构建列表组件:

  • 每个项目都可以选择
  • 选择状态更改DOM(某些类绑定)
  • 用户可以在列表组件中绘制一个矩形,一次选择多个项目
  • 理想情况下,整个行为可以抽象为混合
问题:选择标志在哪里

尝试

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

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

2) 将状态移出子组件

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

3) 重新引入代理

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

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

而且,它对mixin也不起作用。如果我想抽象出一些
HasSelection
mixin和
HasFoldableItems
mixin,以及
Sortable
mixin,它们都需要一些状态

返回绘图板

有没有更好的模式我还没有找到

我发现了以下相关问题,但没有任何结果:

  • (2012年,与我的上文第3条相似)
  • (列表中的一些关键问题与此相关)

好问题-我实际上去了一位核心的ember团队成员那里寻找答案,目前的答案是服务。因为组件最好保持无状态(在大多数情况下),所以可以利用服务来持久化不适合服务器持久化模型的状态

这里有一个很好的例子,Stef Penner展示了如何在你的ember应用程序中保存“电子邮件草稿”(不是持久化的后端)

示例组件供参考(来自上面的github项目)


现在正在读国家服务的东西。这种方法看起来非常好,基本上组件在使用相同的
stateName
时将共享状态。但是,stateName似乎必须预定义,这意味着相同组件的所有实例将共享相同的状态。但我看到了如何添加一级间接寻址(只有一个服务,可以动态创建新的状态名)。这种方法比我在问题中的三种方法都好。不过,我还是想把这个问题留待一会儿,看看是否还有其他问题出现。好的。指向模块有一个非常好的概念。这应该在ember.js教程中有所体现。它并不完全适合用例,因为它针对的是不需要生命周期管理的长期UI状态,但我可以基于这样的想法:我将状态存储作为一个对象,父组件(通过attr)将其注入子组件。缺点:不再是单身汉了,所以可能有点违背了这个想法。优点:我可以将组件的生命周期和状态结合起来,这在这里是有意义的。@思百吉有没有可能为您的解决方案提供一个单独的答案?Toran是正确的,当状态变得太复杂以至于单个组件无法管理时,将状态从ui中拉出来并粘贴到服务上。我在这里写了一条评论:
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'));
    }
  }
});