Angular 5:如何在路由守卫中访问父组件的非全局服务
解决Angular路由守卫中获取组件级注入服务的问题
首先得搞清楚为什么会出现no provider for MyService这个错误:你的MyService是注册在ParentComponent的提供者中的,属于组件级注入器;而路由守卫(比如canActivate里的MyGuard)默认是在模块级注入器中创建的,模块注入器无法访问组件级注入器里的服务,所以直接注入肯定找不到。
而且你说得对,ActivatedRouteSnapshot里的component只是类定义,绝对不能自己手动创建组件实例——这会绕过Angular的生命周期管理,不仅拿不到正确的服务实例,还可能引发各种奇怪的问题。
那正确的做法是什么?咱们可以通过路由快照的父路由注入器来获取MyService,具体实现如下:
实现步骤
- 在
MyGuard的canActivate方法中,利用传入的ActivatedRouteSnapshot参数,访问其父路由的注入器 - 从父路由注入器中获取
MyService实例
示例代码
import { Injectable } from '@angular/core'; import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router'; import { MyService } from './my.service'; @Injectable({ providedIn: 'root' // 守卫通常注册在根注入器 }) export class MyGuard implements CanActivate { canActivate( route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean { // 从父路由的注入器中获取MyService实例 const myService = route.parent?.injector.get(MyService); if (!myService) { // 处理找不到服务的极端场景(比如父路由不存在) return false; } // 这里使用myService执行你的守卫逻辑 console.log(myService.someMethod()); return true; // 根据实际业务逻辑返回true/false } }
原理说明
当Angular加载ParentComponent时,会为它创建一个组件级注入器,这个注入器会和父路由的ActivatedRouteSnapshot关联。通过route.parent我们可以拿到父路由的快照,再通过它的injector属性就能访问到ParentComponent的注入器,进而获取到注册在其中的MyService实例——这个实例和你在两个子组件中注入的是同一个,完全符合你的需求。
额外提示
如果你的路由结构是多级嵌套的,可以通过route.pathFromRoot遍历整个路由树,找到对应的父路由注入器。不过在你的场景里,直接用route.parent就足够了。
内容的提问来源于stack exchange,提问作者danwellman
相关产品推荐
相关产品推荐

