当我们在创建 angular 的服务时,providedIn的选项默认都是root,有的小伙伴就会问了,这个providedIn是做什么的,除了 root 还能填其他值嘛 🤔。
查阅angular(v15)文档,发现providedIn总共有 5 种值
root:在大多数应用程序中是指应用程序级注入器。any:在每个惰性加载的模块中提供一个唯一实例,而所有热切加载的模块共享一个实例。null:等效于undefined。可注入物不会在任何范围内自动提供,必须添加到@NgModule、@Component或@Directive的providers数组中。platform:由页面上所有应用程序共享的特殊单例平台注入器。Type<any>- 将可注入物与@NgModule或其他InjectorType相关联。此选项已弃用。
angular 官网的文档一如既往的不给力 😳,只有选项,并没有示例说明,下面我们通过几个具体的例子,来看看这几个选项具体的表现 😎
root
providedIn 最常见的就是 root,因为服务创建时,默认值都是 root,
root 就是在项目根目录创建一个实例,所有注入这个服务的组件,都会共享这个实例。
利用这个特性,我们经常使用它去做组件间的传值,或者做全局的传值。
我们按照下面步骤,创建一个示例
- 创建 2 个
module, 分别命名为root-first、root-second,并且使用路由懒加载 - 创建
rootService,providedIn为root, 创建变量count - 给 2 个
moudlue中的component都引入rootService, 显示变量count,并且添加+按钮使count + 1
|
如图,我们可以看到,在 root-first 中改变变量的值,在 root-second 中一样会起效,同样在 root-second 中改值,root-first 也会生效。
any
每个懒加载的模块中会分别共享一个实例,而所有非懒加载的模块共享一个实例
什么意思呢,同样是上面的代码,我们把 service 中的providedIn改为any,这个时候,在 root-first 中改变值,root-second 中的值就不会变化了
|
这个时候如果我们把 root-first 改为急性加载,并在 app.component 中也注入 root.service
|
这个时候我们发现,在 app.component 和 root-first 中 count 是共享的 🤓,但是 root-second 中的 count 是不与他们共享的, 这是因为 root-second 是懒加载的,而其他的则是急性加载所以他们会共享数据
null
如果我们把providedIn设为 null 或者不填,那么此时,就需要在 module 中的 providers 注入这个服务,否则就会报错 😲
|
此时我们在所有用到 root.service 服务的 module 中全部注入 service, 它的表现形式和 any 一样,即在每个懒加载的模块中会分别共享一个实例,而所有非懒加载的模块共享一个实例
|
platform
页面上所有应用程序共享的平台注入器的特殊单例。
创建 appMoudle2
|
同时在main.ts中引入
|
在index.html中引入app-root2
|
然后我们把 root.service 的providedIn设为platform
|
这时,我们发现虽然是 2 个根模块,但是数据还是共享了(没有实时刷新的原因,是因为分属不同根模块,没有触发脏检查)
ngModule
在这里我们新创建一个 ngModule,命名为RootChildModule, 服务的providedIn我们设置RootChildModule,并且在app.module中引入RootChildModule
|
此时的效果与root相同,不同之处在于,只有在 component 中引入 root.service,该服务的代码才会被打包进去,否则代码将会被摇树优化。
为了验证此功能,我们把 root.service 移出,新建/child/root.service 文件
|
同时新建/child/root-child.module 来给 providedIn 提供值
|
然后修改一下app.module的代码
|
注意,此时,我们没有在任何地方注入root.service, 此时我们在浏览器 network 中搜索 root.service 中的代码
结果可知,代码没有打包进去
此时,我们在RootFirstComponent中注入root.service
|
此时,再去 network 中搜索,发现已有代码
我们再删除RootFirstComponent中已注入的root.service,并且把providedIn的值改为null,并且在RootFirstModule里面申明RootService
|
|
此时搜索 network, 虽然已经删除了注入部分的代码,但是 root.service 中的代码依然能搜索到
这里,我们不用providedIn:root举例的原因是,服务的 providedIn 为 root 时,不用声明,也能使用,所以自然代码也会被摇树优化掉,我想这也是 ngModule这个选项被弃用的原因。
总结
实际中,我们使用比较多的只有root和null,
root同时具备摇树优化的能力,但是他会在全局共享数据,并且没有限制,任意地方都可以使用null可以根据情况,在需要的时候使用providers注入使用,并且会区分懒加载和急性加载
platform虽然有实际的应用场景,但是使用比较少,而any和ngModule都可以被any和root取代
源码
- 本文作者: luckyship
- 本文链接: https://luckyship.github.io/2024/04/13/2024-04-13-angular-service-providedIn/
- 版权声明: 本博客所有文章除特别声明外,均采用 MIT 许可协议。转载请注明出处!
