适用场景
尤其针对一个变量需要从顶层组件开始透传,途径很多个子组件最后在第n代子组件使用的时候。对于这些途经的子组件而言,它们不但不使用而且完全不关心该变量具体是什么,只是作为一个传递工具罢了。这种情况下,使用依赖注入最方便。举例:
- 父组件A:透传一个变量 x1 。
- A的子组件A1 的子组件A11 也就是A的第二代组件中才会使用。这时候如果使用
props
进行传值,这些中间组件都仅仅作为一个数据传递的工具罢了,会出现很多的数据冗余。
依赖注入
依赖注入通过两个内置方法:
- 父组件
provide
提供一个变量或方法 - 子组件
inject
注入一个从祖先组件或整个应用提供的值
使用举例:
- 父组件
// 父组件
<script setup>
import { ref, provide } from 'vue'
import { fooSymbol } from './injectionSymbols'
// 提供静态值
provide('foo', 'bar')
// 提供响应式的值
const count = ref(0)
provide('count', count)
// 提供时将 Symbol 作为 key
provide(fooSymbol, count)
</script>
- 子组件
<script setup>
import { inject } from 'vue'
import { fooSymbol } from './injectionSymbols'
// 注入不含默认值的静态值
const foo = inject('foo')
// 注入响应式的值
const count = inject('count')
// 通过 Symbol 类型的 key 注入
const foo2 = inject(fooSymbol)
</script>
props和依赖注入
- props透传
props透传是下面这种模式的,当有一个由多层级嵌套的组件形成的一个巨大的组件树时,某个深层的子组件需要一个较远的祖先组件中的部分数据。这种情况下如果仅使用 props ,则必须将其沿着组件链逐级传递下去,这会非常麻烦:
- 依赖注入
依赖注入是如下这种模式的。provide
和 inject
可以很好的帮助我们解决这一问题。 一个父组件相对于其所有的后代组件,会作为依赖提供者。任何后代的组件树,无论层级有多深,都可以注入由父组件提供给整条链路的依赖。
- 依赖注入的提供层通过
provide
提供数据 - 使用层通过
inject
注入数据
使用symbol
我们已经了解了如何使用字符串作为注入名。但 如果你正在构建大型的应用,包含非常多的依赖提供,或者你正在编写提供给其他开发者使用的组件库,建议最好使用 Symbol 来作为注入名以避免潜在的冲突(PS:建议学习Symbol特性)
symbol的使用:
- 新建一个用于存储symbol的文件
// keys.js
export const myInjectionKey = Symbol()
- 在提供方组件中
// 在供给方组件中
import { provide } from 'vue'
import { myInjectionKey } from './keys.js'
provide(myInjectionKey, { /*
要提供的数据
*/ });
- 在使用方组件中
// 注入方组件
import { inject } from 'vue'
import { myInjectionKey } from './keys.js'
const injected = inject(myInjectionKey)