Ember 组件发送动作到路由

Posted

技术标签:

【中文标题】Ember 组件发送动作到路由【英文标题】:Ember component send action to route 【发布时间】:2017-07-06 20:13:08 【问题描述】:

我有两个组件,一个坐在另一个组件上。我需要从子组件向主路由发送事件(两个组件在同一路由中使用)

请告诉我是否有任何标准方法可以做到这一点。

【问题讨论】:

【参考方案1】:

从 Ember 3.14 开始,Octane,我们可以用一种现代、明确、简洁和清晰的方式解决这个问题——我们将在这个短暂的中场休息后开始:

我需要从子组件向主路由发送事件

虽然这是可能,但强烈建议不要这样做,因为路由不应该有动作并且应该是无状态的。也就是说,我们可以通过以下几种方式解决动作通过深层组件的问题:

"Data Down, Actions Up" 使用服务

对于第一个,Data Down,Actions Up,您可以根据需要将参数向下传递任意多个组件层

// app/controllers/application.js:
@action
dance()
  console.log('┏(-_-)┓┏(-_-)┛┗(-_- )┓')


// app/templates/application.hbs
<Foo @dance=this.dance />

// app/components/foo.hbs
<Bar @dance=@dance />

// app/components/bar.hbs
<button on 'click' @dance>Dance!</button>

这可能是一个滑坡。虽然只有两个组件来记录数据和 action 备份(在这种情况下单击后),但这似乎并不费力,但许多 UI 可能有 10 多个组件深度,并且将适用于称为 Prop-Drilling 的反模式。

为了减轻螺旋钻,我们的工具箱中有另一种方法可以使用。服务!

// app/services/my-service.js
@action
dance()
  console.log('┏(-_-)┓┏(-_-)┛┗(-_- )┓')


// app/components/bar.js
import Component from '@glimmer/component';
import  inject as service  from '@ember/service';

export default class Bar extends Component 
  @service myService;


// app/components/bar.hbs
<button on 'click' this.myService.dance>Dance!</button>  

深层嵌套的组件可以直接访问动作,而不需要经过几层传递——这会导致代码更易于维护和更清晰。

资源

Classic to Octane Cheat Sheet Octane Edition Documentation Page

【讨论】:

!remindme 2 天:查看代码和框是否已修复,并提供实时工作代码示例 虽然这显示了一个很好的模式,但它根本没有回答这个问题。我在试图弄清楚如何在路由上调用内置动作(刷新)时偶然发现了这一点,如果试图避免添加控制器 + 额外动作 + 使用 sendAction 只是为了这个目的。似乎是路由服务缺少的功能。【参考方案2】:

对于简短的回答,您可以使用ember-route-action-helper 插件。

<button action (route-action 'onButtonClick')>ClickToCallRouteAction</button>

共有三种action通信方式,

1.旧式经典函数样式 即,将函数名称作为字符串从上到下传递。并且在所有地方我们需要定义相同的功能并提供。使用sendAction 冒泡。和 send 从控制器到路由层次结构的方法冒泡。

不鼓励这样做。 经典风格样张actions twiddle

2。关闭操作 使用action 辅助传递函数,而不仅仅是字符串。这样您就不需要在任何地方定义它。 sample twiddle for closure actions风格

3. route-action-helper addon 只需使用 route-action 助手包装函数,您就可以从任何地方直接调用路由操作。

Sample twiddle

Classic 风格与 Closure 风格的比较以及为什么 Closure 更可取?

在经典风格中,您需要在每个级别定义动作并使用 sendAction 触发每个级别的动作,直到您完全摆脱嵌套。 您可以在关闭操作中返回值,但不能在经典操作中返回。 您可以在闭包操作中使用 curry 值,但不能在经典操作中使用。 如果找不到操作,关闭操作会立即失败。但是经典的动作设计,只会在调用时懒惰地引发错误 价值观。 编码复杂性,例如谁来处理操作和执行业务逻辑? 在闭包中,您可以结合 action 和 mut helper 来设置具有值的属性。 onclick=(action (mut title) value="titlevalue") 在闭包中,您可以指定目标对象来调用函数。 (action 'save' target=session) 将查看session 对象上的actions 哈希,而不是当前上下文。

一些关于此的有希望的文章, - miguelcamba 文章ember-closure-actions-in-depth - 引燃文章send-closure-actions-up-data-owner - emberjs 博客1.13 release article - 船坞 - ember-best-practice-stop-bubbling-and-use-closure-actions - 来自 Ember 地图的博客 Why action helper? - Alisdair McDiarmid 的博客ember-closure-actions-have-return-values - 来自 alexdiliberto 的博客 ember-closure-actions

【讨论】:

为什么不鼓励old style classic functions style?您能否详细说明(1)和(2)之间的区别。 @LiXinyang 更新了差异以及为什么首选闭包以及一些好文章。 感谢您抽出宝贵时间@kumkanillam。点赞! +10 所有这些参考都很棒 爱你@kumkanillam 这个关闭动作节省了我的一天,可能还有很多小时的研究如何做到这一点。 很好的答案,谢谢@kumkanillam。参考文献很棒,谢谢。如果可以的话,我会投票 x10。

以上是关于Ember 组件发送动作到路由的主要内容,如果未能解决你的问题,请参考以下文章

从 Vuex 动作和组件更改路由

Ember.js:从嵌套路由调用 ApplicationRoute 的操作

Ember.js 路由器:如何动画状态转换

Ember JS 过渡到嵌套路由,其中​​所有路由都是视图中的动态段

Ember:你如何从路由器访问模型?

如何使用异步路由进行 Ember 单元测试?