You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

EmberJS 2.14:使用组件复用路由动作失败,如何实现DRY应用?

解决EmberJS 2.14中组件无法触发路由动作的问题

嘿,我完全懂你在Ember 2.14里搞DRY应用时遇到的头疼事——组件触发路由动作失败,还报找不到saveStuff的错对吧?这个问题的核心是组件的动作上下文默认不是路由,它只会在自己或父组件/控制器的动作里找,所以直接绑路由的动作自然找不到。下面给你几个适配Ember 2.14的解决方案,从快速修复到更符合DRY的优化都有:

方案1:通过控制器代理路由动作

Ember模板的默认上下文是控制器,所以我们可以在控制器里把路由的动作“转发”出去。如果你的new路由还没有控制器,先新建一个:

// app/controllers/new.js
export default Ember.Controller.extend({
  actions: {
    saveStuff(newStuff) {
      // 调用路由里的同名动作
      this.send('saveStuff', newStuff);
    }
  }
});

之后你的new.hbs不用改,组件就能通过控制器找到路由的saveStuff动作了——控制器相当于中间层,把模板的动作请求转发给路由。

方案2:直接指定动作的目标为路由

在Ember 2.14里,你可以给action助手指定target参数,直接把动作的执行目标指向当前路由,这样就能跳过控制器直接触发路由动作:

{{basic-button texte="Create" theAction=(action 'saveStuff' model target=this.route)}}

这里的this.route在模板上下文里就是当前的路由实例,动作会直接调用路由里的saveStuff方法,简单直接。

方案3:用服务封装复用逻辑(终极DRY方案)

如果这个保存逻辑需要在多个地方复用,把它抽成服务是最符合DRY原则的做法——把业务逻辑集中在一个地方,哪里需要就注入哪里,不用在每个路由里重复写代码。

首先新建一个处理Stuff逻辑的服务:

// app/services/stuff-manager.js
export default Ember.Service.extend({
  // 注入路由服务用来做页面跳转
  router: Ember.inject.service(),

  saveStuff(newStuff) {
    return newStuff.save().then(() => {
      this.get('router').transitionTo('stuffs');
    });
  }
});

然后在你的组件里注入这个服务,把保存逻辑移到组件里:

// app/components/basic-button.js
export default Ember.Component.extend({
  stuffManager: Ember.inject.service(),

  actions: {
    handleSave() {
      this.get('stuffManager').saveStuff(this.get('model'));
    }
  }
});

最后修改模板,绑定组件自己的动作:

{{basic-button texte="Create" theAction=(action 'handleSave') model=model}}

这样不管是在哪个路由或组件里,只要注入这个服务就能复用保存逻辑,彻底避免重复代码。

为什么原来的代码会报错?

你之前的代码里,(action 'saveStuff' model)是在模板上下文(默认是控制器)里找saveStuff动作,但路由的actions并不会暴露在模板上下文里,所以组件找不到这个动作,就抛出了那个断言错误。

内容的提问来源于stack exchange,提问作者Syl

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 08:45:26