从Ember Service跳转Ember Route报错:Cannot read property 'toRoute' of undefined
解决Ember Service中调用
toRoute时出现"Cannot read property 'toRoute' of undefined"的问题 我之前在做Ember项目的时候也碰到过一模一样的问题,其实根源很简单——Ember的Service是全局单例,本身并没有内置路由(router)的引用,而Controller因为和对应的Route紧密绑定,天然就能访问到路由相关的方法,所以在Controller里调用toRoute完全没问题,但Service里就不行。
下面给你可行的解决方案,核心都是让Service能访问到路由服务:
方法一:注入router服务(推荐)
在你的Service里显式注入Ember内置的router服务,这样就能调用路由跳转的方法了。代码示例如下:
// app/services/your-custom-service.js import Service from '@ember/service'; import { inject as service } from '@ember/service'; export default class YourCustomService extends Service { @service router; // 注入内置的router服务 navigateToTargetRoute() { // 现在可以正常调用跳转方法了,两种写法都可行 this.router.transitionTo('your-target-route'); // 官方推荐写法 // this.router.toRoute('your-target-route'); // 和transitionTo是别名,效果一致 } }
方法二:通过Controller传递路由引用(备选,不推荐)
如果你暂时不想在Service里注入router,也可以在调用Service方法时,把Controller的路由引用传过去,但这种方式会让Service和Controller产生耦合,不利于代码复用和维护,只作为临时备选:
// 在你的Controller里 import Controller from '@ember/controller'; import { inject as service } from '@ember/service'; export default class YourController extends Controller { @service yourCustomService; someAction() { // 把当前Controller的路由引用传给Service this.yourCustomService.navigateToTargetRoute(this); } } // 在你的Service里 export default class YourCustomService extends Service { navigateToTargetRoute(controller) { controller.toRoute('your-target-route'); } }
补充说明
toRoute其实是transitionTo的别名,Ember官方更推荐使用transitionTo,功能完全一致,但语义更清晰。- 如果你用的是Ember Octane之前的版本(比如Ember 3.10及更早),注入服务的语法可能是
inject: ['router'],不过现在装饰器@service的写法是主流。
内容的提问来源于stack exchange,提问作者punith gowda
相关产品推荐
相关产品推荐

