由 Angular 路由守卫问题了解更深的 Angular 架构
今天有同事遇到了一个问题,她在路由守卫的构造器中引入新的依赖后,相应的 routing-module 报错,贴图如下:
报错提示的很明显,路由守卫需要添加 @Injectable()
注解。加上后确实报错消失了,但为什么呢?因为原来项目是一直正常运行的!!!
为此,我看了 Angular 源码后,终于解开了这个疑问
首先,我们把疑问先抛出来:
- 原先的路由守卫,没有加注解,为什么可以正常运行?
- 现在的路由守卫,引入新依赖后,为什么报错?
以下是一些解决疑问的历程
Angular 路由守卫原理
以上操作,将路由配置变为路由树。
canDeactivate(离开),canActivate(进入) 中配置的路由守卫会组合成路由树中,相应路由的方法(Function)。
当路由跳转的时候,会触发 Angular 中对 canDeactivate 及 canActivate 的检测,当存在路由守卫时,会先执行路由守卫,如下图源码:
Angular 依赖注入
我们似乎没在意过,我们一直认定:在 Angular 中,添加 @Injectable() 注解之后的 class 才被认定为依赖,而 NgModule 中 providers 里面必须是可注入的依赖。
但 providers 的类型其实可以是 any[],如下图:
所以,providers 中能配置的,不仅仅是这些,它甚至可以是字符串,只是我们可能从未在意过~
问题解释
由上述 路由守卫原理 中可看出,Angular 的路由守卫并不是一个依赖,而是一个方法。下图源码中对路由守卫的校验只校验了其是否是方法(Function)。
也就是说 路由守卫 并不需要是“真正的”依赖,就可以当做路由守卫运行
这解释了为什么之前不加 @Injectable() ,便可以正常运行
而后面构成依赖链条件后,Angular 校验出了其中有一环不是“真正的”依赖
这就解释了为什么后面构造器中加入新依赖后,就出现了报错。也就是说,虽然 providers 中可以不是 Provider
,但如果其中引入了其它 Provider
,那它必须也是 Provider
上面这句话可能比较拗口,希望读者细品能品明白