重学 Vue3 之依赖注入

lxf2023-05-05 11:20:01

依赖注入

父子组件通信的时候常常使用 prop 和 emit 即可实现需求,但是如果遇到需要跨组件进行通信的场景,使用 prop 和 emit 的话会出现多余的“中间组件”,这显然不利于开发维护。依赖注入就是为了解决上述问题出现的。

依赖注入包括 provide 和 inject 两个函数。provide 的第一个参数是注入名,可以是字符串或者 symbol,第二个参数注入值,可以是任意值。inject 函数第一个参数是注入名,可以是字符串或者 symbol,第二个参数是默认值,可以是字符串,返回复杂值的工厂函数。也可以直接是一个普通函数,不过这个时候必须增加第三个参数 false。

// app.vue
<script setup>
import Mid from './Mid.vue'
import { provide, ref } from 'vue'

const location = ref('Jiangxi')

const changeLocation = (value) => { location.value = value }

provide('location', { location, changeLocation })
<script>

<template>
    <Mid />
</template>
// mid.vue
<script setup>
import Child from './Child.vue'
<script>

<template>
    <Child />
</template>
// child.vue
<script setup>
import { inject } from 'vue'

const { location, changeLocation } = inject('location', () => ({ location: '', changeLocation: () => { } }))

function change(place) {
  changeLocation(place)
}
<script>

<template>
  <div>{{location}}</div>
  <input style="color:black" @input="(event)=>change(event.target.value)" />
</template>

重学 Vue3 之依赖注入

上述代码演示了组件间通过 provide 和 inject 进行传值的场景。App.vue 文件通过 provide 函数将 location 和 changeLocation 通过 provide 函数传递给子孙组件。Mid 组件作为中间过渡层。Child.vue 组件通过 inject 函数接受传递过来的 location 和 changeLocation,将 location 显示到页面上,再展示一个输入框,用户输入内容后即可调用传递过来的 changeLocation 函数来修改 location。从截图可以看出 location 由原来的 Jiangxi 变成了 Guangzhou。

值的注意的是,实际项目中一般不使用字符串作为注入名,而是使用 symbol,这样保持全局唯一性。另外,inject 函数使用工厂函数作为默认值,避免在不使用的情况下进行复杂计算和产生副作用。

结论

从 API 的角度理解依赖注入是很方便的。祖先组件使用 provide 函数进行传值,传参包括注入名和注入值。子孙组件使用 inject 函数接收值,传参包括注入名和默认值,返回的就是注入值。

参考资料:cn.vuejs.org/