组件如何响应操作?

Sam*_*off 1 ember.js

tl; dr:数据可以发送进出组件,但我只知道如何发送动作.有没有办法发送行动?


在我的Ember应用程序中,我有类似Google地图中的以下用户界面:

在此输入图像描述

背景图对应于PinsRoute/PinsView/PinsController,它显示了许多引脚.单击其中一个时,输入PinRoute将叠加层渲染到的窗口{{outlet}}.大地图和缩略图(在Google地图图片中,显示"街景"的图片)都是组件:FullscreenMapComponentThumbnailMapComponent.

在Google地图中,当您点击"街景视图"时,它会将主地图平移并缩放到所选点.这基本上就是我想弄清楚如何连线.

当用户点击我的"streeth view"时ThumbnailMapComponent,我可以发出一个PinsRoute可以处理的动作.问题是,我怎样才能找到我的FullscreenMapComponent并调用适当的方法(.panToSelected()在这种情况下)?

Sam*_*off 6

这是一个很好的解决方案.让组件将其自身注册到呈现的任何控制器,这样您就可以在操作处理程序中访问该组件.

在我的例子中,我为我的组件添加了一个方法

App.FullscreenMapComponent = Ember.Component.extend({

  ...

  _register: function() {
    this.set('register-as', this);
  }.on('init')

});
Run Code Online (Sandbox Code Playgroud)

和我的控制器的属性:

App.SensorsController = Ember.ArrayController.extend({

  fullscreenMap: null,

  ...

});
Run Code Online (Sandbox Code Playgroud)

在我的模板中,我将两个绑定到我的新register-as属性:

// sensors.hbs

  {{fullscreen-map data=mapData
    selectedItem=currentSensor
    action='selectSensor'
    deselect='deselectSensor'
    register-as=fullscreenMap }}
Run Code Online (Sandbox Code Playgroud)

现在,假设我点击上面的缩略图并发送一个冒泡到我的动作ApplicationRoute,我现在可以这样做:

// ApplicationRoute.js

actions: {
  panTo: function(latLong, zoom) {
    this.controllerFor('sensors').get('fullscreenMap').panTo(latLong, zoom);
  }
}
Run Code Online (Sandbox Code Playgroud)

普雷斯托!响应操作的组件.

更新(2016年10月6日)

哇,我在两年内学到了很多东西.

我不再推荐这个解决方案了.通常,您应该努力使组件具有声明性,并使其输出和行为完全取决于其状态.相反,我在这里的原始答案使用命令式方法解决了问题,这种方法很脆弱,难以理解,并且不容易扩展(如果我们想将地图的位置与URL联系起来怎么办?).

如果我重构这个特定的组件,我可能会{{fullscreen-map}}接受latLongzoomparams.如果来自外部的人设置了这些,则地图将响应并自行更新.您可以didReceiveAttrs在组件内使用以响应参数更改,然后从那里调用panToGoogle API 的命令式方法.

需要注意的是,即使您必须与命令式方法(可能是因为第三方库)进行交互,也要努力使自己的组件API尽可能具有声明性.首先看起来"向下发送一个动作"通常可以表示为状态的某种功能,并且该状态是您想要识别和明确的状态.