Ember.js 如何在Emberjs中的控制器之间传递事件?更新:如何在余烬中设计自动完成

Ember.js 如何在Emberjs中的控制器之间传递事件?更新:如何在余烬中设计自动完成,ember.js,Ember.js,场景:一个具有自己的控制器和视图的自动完成小部件,因此它是一个模块化组件,一旦移出实验阶段,就可以使用{render“autocomplete”}或新的{control}助手将其呈现到任何其他视图中。为了使自动完成独立于其他所有内容,它不应该知道父控制器,也不应该知道在选择某个项时会发生什么操作 我一直在试图弄清楚如何使用Ember.Evented mixin,这样我就可以从自动完成触发一个事件,比如itemSelected,然后它会冒泡出来并被父视图或控制器捕获 所以像往常一样,Ember文档

场景:一个具有自己的控制器和视图的自动完成小部件,因此它是一个模块化组件,一旦移出实验阶段,就可以使用{render“autocomplete”}或新的{control}助手将其呈现到任何其他视图中。为了使自动完成独立于其他所有内容,它不应该知道父控制器,也不应该知道在选择某个项时会发生什么操作

我一直在试图弄清楚如何使用Ember.Evented mixin,这样我就可以从自动完成触发一个事件,比如itemSelected,然后它会冒泡出来并被父视图或控制器捕获

所以像往常一样,Ember文档是缺乏的。尤其是在余烬事件方面。(公平地说,文档已经走过了很长一段路,但我仍然想要更多。他们说约定优于配置,但没有提供约定!)总之,抱怨够了,文档显示了ember evented在通用对象上的工作,我发现这篇文章更深入了一点:但我认为一个带有控制器、视图、路由和组件(如autocompletes)的更真实的示例会更好

我认为这些类型的事件应该是视图的责任,但这不起作用,所以我也将mixin放在了控制器上。当您看到jsFiddle时,这将是有意义的

在其中,您将看到一个假的autocomplete控制器,它只是从设备中获取一组静态内容,并为每个项目显示两个按钮,您可以单击这些按钮从视图或控制器触发事件。在一个实际示例中,将观察文本框中的输入,并更新内容,以根据输入提供不同的建议,但这对于本示例并不重要

jsFiddle: 我最怀疑这些行:
this.on(“myEvent”,this.addItem)
因为触发事件的函数显然正在被调用,但似乎事件没有传播,或者索引控制器和视图实际上没有正确设置以响应事件

以下是主要问题:

  • 我需要更改什么,以便索引控制器能够响应自动完成触发的事件

  • 实现这一点最适合MVC的方式是什么?触发/接收是否应在视图/控制器上

  • 有更好的方法吗

  • 旁注: 我目前的解决方案是在自动完成控制器中添加
    needs:[“index”]
    ,而不是触发事件,我只是从自动完成控制器显式调用index控制器中的方法。这有很多问题,首先是控制器之间的紧密耦合,如果假设自动完成会影响多个控制器,或者在其他地方重复使用,并且必须重新配置等,则无法很好地扩展

    希望我解释得足够清楚。感谢您的帮助。

    哇,好问题

    为了使自动完成独立于其他所有内容,它不应该知道父控制器,也不应该知道在选择某个项时会发生什么操作

    是的,我认为你在尽可能地保持事物孤立方面走在了正确的轨道上

    有更好的方法吗

    我认为是的,应该使用RC6中引入的新“组件”功能。有关详细信息,请参阅

    使用组件方法,您可以实现自动完成独立于父控制器的目标,以及选择项时发生的情况。这与内置的Ember.Select视图的操作非常接近。例如:

    {{app-autocomplete items=model selectedItem=selectedPerson}}
    
    在这里,我设置了自动完成的项,并选择了editem属性以绑定到当前控制器上的值。appautocomplete不知道这些绑定的另一端是什么,也不知道当值发生变化时调用方将如何反应。然后,您的索引控制器可以观察它自己的selectedPerson属性,并在其更改时作出反应。大概是这样的:

    App.IndexController = Ember.ArrayController.extend({
      selectedPerson: null,
      selectedPersonDidChange: function() {
          Ember.Logger.log("Index.contoller addItem: ", this.get('selectedPerson').toString());
      }.observes('selectedPerson'),
    });
    
    组件也非常简单。它希望它的
    items
    属性包含一个具有
    名称的对象数组,当单击一个时,它会设置自己的
    selectedItem
    属性

    <script type="text/x-handlebars" id="components/app-autocomplete">
      {{input}}
      {{#each item in items}}
        <li><button {{action itemSelected item}}>{{item.name}}</button></li>
      {{/each}}
    </script>
    
    App.AppAutocompleteComponent = Ember.Component.extend({
    itemSelected: function (item) {
      this.set("selectedItem", item);
          Ember.Logger.log("component.itemSelected: myEvent triggered wit h: ", item.toString());
    }
    });
    
    
    {{input}}
    {{{#项目中的每个项目}
    
  • {{item.name}
  • {{/每个}} App.AppAutocompleteComponent=Ember.Component.extend({ 所选项目:功能(项目){ 此.set(“selectedItem”,项); Ember.Logger.log(“component.itemSelected:myEvent被h触发:”,item.toString()); } });

    这里的完整示例:

    根据Mike Grassotti的建议,我们认为Ember.Evented实际上不是正确的解决方案,并开始研究{{control}}和Ember.Component

    我仍然不确定他发布的JSFIDLE链接,但我从他的帖子中获得了足够的信息,并创建了一个jsBin来模拟使用{{control}}和使用Ember.Component的尝试。每个组件都有优点和缺点,但最终,Ember.Component获胜,因为{{control}}没有正确绑定

    见: (我不知道如何在JSFIDLE中设置ENV.EXPERIMENTAL_CONTROL_HELPER,这就是为什么我使用jsBin,最终我更喜欢jsBin的原因…)

    在其中,您将看到两个自动完成。一个是用{control}}助手实现的,它使用一个AutocompleteController和AutocompleteView,另一个是Mike Grassotti建议的Ember.Component

    #1使用{{control}助手:

    优点:我喜欢为自动完成设置控制器的想法,因为我认为这是一种更好的分离关注点/单一责任的方法。自动完成控制器应该知道如何处理输入框中的文本,如何发送请求,以及在需要时解析数据

    缺点:我遇到的第一个问题是控件助手似乎需要