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

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

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

【问题讨论】:

    标签: ember.js


    【解决方案1】:

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

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

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

    对于第一个,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>  
    

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

    资源

    【讨论】:

    • !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。
    猜你喜欢
    • 2015-09-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-25
    • 1970-01-01
    • 2017-01-31
    相关资源
    最近更新 更多