Angular中providedIn: 'root'与在App组件注册服务的区别是什么
Angular两种服务注册方式的核心技术差异
我们可以把服务注册方式分为两类,核心差异是绑定的注入器不同:
第一类:根注入器注册(providedIn: 'root' 与 AppModule providers 注册)
这两种方式本质都是将服务注册到应用全局的根注入器上,你之前的认知基本正确:
- 两种方式默认都会生成全应用唯一的单例实例,所有可以访问根注入器的类都可以拿到同一个实例
- 两者唯一的区别是
@Injectable({ providedIn: 'root' })支持摇树优化:如果整个应用没有任何地方依赖该服务,打包时会自动剔除服务相关代码,减少包体积;而AppModule的providers数组注册的服务无论是否被使用,都会被打包进最终产物。
第二类:组件级注册(例如AppComponent的providers数组注册)
这种方式是将服务注册到对应组件专属的组件注入器,和根注入器完全独立:
- 组件注入器的层级和Angular组件树完全绑定,依赖查找遵循「自下而上」规则:组件注入依赖时先查自己的注入器,找不到再查父组件注入器,直到根组件的注入器,最后才会去根注入器查找
- 你遇到的MatDialog无法获取实例的问题,本质原因是:通过代码动态创建的组件(包括MatDialog弹窗、ViewContainerRef动态生成的组件等)默认不属于当前页面的组件树,它们的默认父注入器是根注入器,所以不会到AppComponent的注入器里查找服务,自然拿不到对应实例,甚至如果根注入器没有注册该服务会直接抛出注入错误。
如果需要动态组件也能拿到组件级注册的服务,创建时手动指定注入器即可,比如打开MatDialog时传入当前组件的viewContainerRef配置项,就可以继承当前组件的注入器层级。
内容的提问来源于stack exchange,提问作者Vítor França
相关产品推荐
相关产品推荐

