【Vue3】19-provide & inject

41 阅读1分钟

1. 作用

用于父组件给子孙组件传值,隔代传值也可以直接一步到位,而不用像 props 那样逐层传递

2. 用法

祖先组件中 provide('key', value)

后代组件中 let data = inject('key')

3. 案例

爷组件中

// App.vue
<template>
    <h1>爷组件</h1>
    <label><input type="radio" name="color" value="red" v-model="colorVar"></label>
    <label><input type="radio" name="color" value="green" v-model="colorVar">绿</label>
    <label><input type="radio" name="color" value="blue" v-model="colorVar"></label>
    <div></div>
    <hr>
    <parent></parent>
</template>

<script setup lang="ts">
import { provide, ref } from 'vue';
import Parent from './components/Parent.vue'  // 引入父组件并使用

let colorVar = ref<string>('red')  // 定义一个变量
provide('colorVar', colorVar)  // 将这个变量 provide 给后代组件

</script>

<style scoped>
div {
    width: 100px;
    height: 100px;
    /* 小妙招:可以直接用 v-bind 绑定 setup 中定义的变量,实现 CSS 的响应式 */
    background-color: v-bind(colorVar);  
}
</style>

父组件中

// Parent.vue
<template>
<h2>父组件</h2>
<div></div>
<hr>
<child></child>
</template>

<script setup lang="ts">
import { inject } from 'vue';
import Child from './Child.vue'  // 引入子组件并使用

let colorVar = inject('colorVar')  // 接收爷组件 provide 的值
</script>

<style scoped>
div {
    width: 100px;
    height: 100px;
    background-color: v-bind(colorVar);
}
</style>

子组件中

// Child.vue
<template>
<h3>子组件</h3>
<div></div>
</template>

<script setup lang="ts">
import { inject } from 'vue';

let colorVar = inject('colorVar')  // 接收爷组件 provide 的值
</script>

<style scoped>
div {
    width: 100px;
    height: 100px;
    background-color: v-bind(colorVar);
}
</style>

实现的效果是,爷组件中选中不同的颜色,父组件和子组件的 div 就会同步切换成对应的颜色

image.png image.png image.png

4. 注意

子组件中对注入值的修改也会同步影响到父爷组件的值
// Child.vue
<template>
<h3>子组件</h3>
<div></div>
<br>
<button @click="changeYellow">修改颜色为黄色</button>
</template>

<script setup lang="ts">
import { inject, ref, Ref } from 'vue';

let colorVar = inject<Ref<string>>('colorVar', ref('pink'))  // 第二个参数是默认值
// let colorVar = inject<Ref<string>>('colorVar)  // 没写默认值

const changeYellow = () => {
    colorVar.value = 'yellow'  // 如果写了默认值,则可以直接赋值
    // colorVar!.value = 'yellow'  // 如果没写默认值,则要写非空断言
}
</script>

<style scoped>
div {
    width: 100px;
    height: 100px;
    background-color: v-bind(colorVar);
}
</style>

点击按钮效果如下

image.png