【发布时间】:2015-08-17 04:04:35
【问题描述】:
我有一个用于 Ember 组件的 mixin,名为 in-view,它的工作是请求将元素显示在视图中。它提供了一个属性,其值是要显示的一段内容,如果该属性与组件的内容匹配,那么我调用scrollIntoView 或等效项。代码如下所示:
// calling template
{{#each items as |item|}}
{{my-item content=item inViewItem=inViewItem}}
}}
// mixins/in-view.js
scrollIntoView() {
if (this.get('content') === this.get('inViewItem'))
this.get('element').scrollIntoView();
}.on('didInsertElement')
// components/my-item/component.js
import InView from 'mixins/in-view';
export default Ember.Component.extend(InView,
这很好用。当我想更改视图中的项目时,我遇到了这个问题。我可以让in-view mixin 观察inviewItem 属性:
}.on('didInsertElement').observes('inViewItem')
这也有效,但似乎有点代码味道。
另外,我的实际代码结构是有一个控制器知道哪个项目应该在视图中,然后它的模板调用一个my-item-list组件,该组件显示包含项目列表的可滚动div,并且在转而调用my-item 组件。这意味着我必须将控制器中的inViewItem 属性向下传递到两个级别,如
// resource/controller.js
inViewItem: something
// resource/template.js
{{my-item-list items=item inViewItem=inViewItem}}
// components/my-item-list/template.js
{{#each items as |item|}}
{{my-item content=item inViewItem=inViewItem}}
}}
我可以通过硬连线my-item 模板来访问控制器上的inViewItem 属性来避免这种情况:
scrollIntoView() {
if (this.get('content') === this.get('controller.inViewItem'))
this.get('element').scrollIntoView();
}.on('didInsertElement')
但那是另一种代码味道;我不想将这种对特定控制器字段的依赖构建到 mixin 中。相反,我可以将控制器属性的 name 传递给组件以进行观察,但这似乎过于笨拙,而且观察名称可变的属性也很棘手。更重要的是,我认为当控制器在 2.0 中消失时这将不起作用。
我想要的本质上是一种“ping”或以某种方式向模板发送消息的方法。我知道原则上这违反了 DDAU 原则,但在这种特殊情况下,我需要的正是以某种方式发送一个“向下操作”——一个告诉组件调整自身以使其进入视野的操作。
当然,我可以放弃 in-view mixin 的整个想法,而只需让控制器深入生成的 HTML 以找到要显示的项目并直接在其上发出 scrollIntoView。但是,这似乎违反了一些关注点分离的原则; my-item 模板将不再完全控制自己。
这种情况推荐的设计模式是什么?
【问题讨论】:
-
创建一个服务来在组件和父控制器之间共享数据怎么样?这可能不是对服务的最佳使用,但它会消除尝试向下发送操作的需要。
-
啊,我被它打败了。
标签: ember.js