vue3-依赖注入 provide & inject

318 阅读1分钟

1. 为什么有provide 和 inject

  • 解决深层组件,props逐级传递的问题 WechatIMG99.jpg

2. 使用方式

  • 父组件 provide
  • 子或孙组件 inject
import { provide, ref } from "vue";
let msg = ref("apple");
provide("fruit", msg);
provide("animal", "cat");
import { inject } from "vue";
let fruit = inject("fruit");
//ref不会被自动解包
console.log(fruit.value, cat); //apple cat

3. 修改状态,统一由提供方控制数据状态

  • provide传递更改方法
let msg = ref("apple");
let changeFruit = (str) => {
  msg.value = str;
};
provide("fruit", {
  msg,
  changeFruit,
});
import { inject } from "vue";
let fruit = inject("fruit");
//修改提供方状态
fruit.changeFruit("banana");
//ref不会被自动解包
console.log(fruit.msg.value); //banana

4. inject默认值

  • 当父级组件没有设置provide。子孙组件已经使用了inject。避免获取到undefined值,可以设置默认值
import { inject } from "vue";
let fruit = inject("fruit", "这是默认值");
//let fruit = inject("fruit"); //ChildDeep.vue:6 [Vue warn]: injection "fruit" not found.
console.log(fruit);
  • 为了避免没有使用到默认值而产生了计算或者副作用。我们可以定义默认值为调用一个工厂函数或者类来实现
let fruit = inject("fruit", () => getDefaultName(), true);
console.log(fruit);

5. 应用层的provide

  • 可以供所有组件使用(可以理解为全局的provide)。对于编写插件来说比较有用,因为插件一般不使用组件的形式来提供值。
    let app=createApp(App);
    app.provide('appprovide','xxx');
    

6. Symbol避免命名冲突

  • 当有大量的依赖提供,或者你想要编写提供给其他开发者使用的库,可以使用Symbol作为注入名,避免注入名冲突
    export const myInjectKey=Symbol();
    
     import { provide, ref } from "vue";
     import { myInjectKey } from "./key";
     provide(myInjectKey, "key为Sylbom类型");
    
     import { myInjectKey } from "./key";
     import { inject } from "vue";
     let data = inject(myInjectKey);
     console.log(data); //key为Sylbom类型