我们之前学习选项式 API 的时候已经写过一篇文章:
19、依赖注入 provide/inject

基础使用

本篇主要看一下组合式 API provide/inject 的区别,在组合式 API 中 provide/inject 都需要从 Vue 中进行导入:

  1. import { provide } from 'vue';
  2. export default {
  3. setup(){
  4. provide(/* 注入名 */ 'message', /* 值 */ 'hello!')
  5. }
  6. }

provide()函数接收两个参数。第一个参数被称为注入名,可以是一个字符串或是一个 Symbol。后代组件会用注入名来查找注入的值。
第二个参数是提供的值,值可以是任意类型,包括响应式的状态,比如一个 ref:

  1. import { provide, ref } from 'vue';
  2. export default {
  3. setup(){
  4. const count = ref(0);
  5. provide('key', count);
  6. }
  7. }

同样的后代组件如果想要使用注入的值,需要从 Vue 中导入inject()方法:

  1. import { inject } from 'vue'
  2. export default {
  3. setup() {
  4. const message = inject('message');
  5. return { message }
  6. }
  7. }

默认情况下,如果该注入名没有任何组件提供,则会抛出一个运行时警告。
如果在注入一个值时不要求必须有提供者,那么我们应该声明一个默认值,和 props 类似:

  1. import { inject } from 'vue'
  2. export default {
  3. setup() {
  4. // 如果没有祖先组件提供 "message"
  5. // `value` 会是 "这是默认值"
  6. const value = inject('message', '这是默认值');
  7. return { value }
  8. }
  9. }

和响应式数据配合使用

当提供/注入响应式的数据时,要尽量的把变更数据的方法都写在父组件内,而不是让子组件去更改提供的数据,使其更容易维护!!!
如果子组件想要更改提供的数据,我们要在供给方组件内声明并提供一个更改数据的方法函数:

  1. // 在供给方组件内
  2. import { provide, ref } from 'vue'
  3. export default {
  4. setup(){
  5. const location = ref('North Pole')
  6. function updateLocation() {
  7. location.value = 'South Pole'
  8. }
  9. provide('location', {
  10. location,
  11. updateLocation
  12. })
  13. }
  14. }
  1. // 在注入方组件内
  2. import { inject } from 'vue'
  3. export default {
  4. setup(){
  5. const { location, updateLocation } = inject('location');
  6. // 执行方法去更改供给方的数据
  7. updateLocation();
  8. }
  9. }

如果你想确保提供的数据不能被注入方的组件更改,你可以使用readonly()来包装提供的值。

  1. import { ref, provide, readonly } from 'vue'
  2. export default {
  3. setup(){
  4. const count = ref(0);
  5. // 用 readonly() 把数据设置为只读
  6. provide('read-only-count', readonly(count));
  7. }
  8. }