当我们在创建 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 许可协议。转载请注明出处!