Provide / Inject
- 当我们需要从父组件向子组件传递数据时,我们使用 props可以实现!
- 想象一下这样的结构:有一些深度嵌套的组件,而深层的子组件只需要父组件的部分内容。在这种情况下,如果仍然将 props 沿着组件链逐级传递下去,可能会很麻烦。
- provide 可以在祖先组件中指定我们想要提供给后代组件的数据或方法,而在任何后代组件中,我们都可以使用 inject 来接收 provide 提供的数据或方法。
- Provide / Inject 在vue 中主要是依靠原型链去实现的! (通过原型链逐级向上查找变量)
-
使用场景:当父组件有很多数据需要分发给其子代组件的时候, 就可以使用provide和inject。
TIPS 你如果传递普通的值是不具有响应式的、需要通过ref reactive 添加响应式
eg: 点击单选按钮,共享颜色背景
App.vue
<template>
<h1>App.vue(爷爷组件)</h1>
<label>
<input v-model="colorVal" type="radio" value="red" name="color" />红色
</label>
<label>
<input v-model="colorVal" type="radio" value="pink" name="color" />粉色
</label>
<label>
<input v-model="colorVal" type="radio" value="yellow" name="color" />黄色
</label>
<!-- 盒子容器 -->
<div class="box"></div>
<hr />
<provide-a />
</template>
<script setup>
import { ref, provide, readonly } from "vue";
import ProvideA from "./components/ProvideA.vue";
const colorVal = ref("red");
// 提供一个数据: 颜色值
provide("color",readonly(colorVal));
</script>
<style>
.box {
height: 50px;
width: 50px;
border: 1px solid #ccc;
/* 绑定 setup 中的变量 */
background: v-bind(colorVal);
}
</style>
src/components/ProvideA.vue
<template>
<h1>ProvideA.vue(父级组件)</h1>
<div class="box"></div>
<hr />
<provide-b />
</template>
<script setup>
import { inject } from "vue";
import ProvideB from './ProvideB.vue'
// 通过 inject 注入读取共享数据
let color = inject("color");
</script>
<style scoped>
.box {
width: 50px;
height: 50px;
border: 1px solid #ccc;
/* 绑定 setup 中的变量 */
background: v-bind(color);
}
</style>
src/components/ProvideB.vue
<template>
<h1>ProvideB.vue(子孙组件)</h1>
<div class="box"></div>
<hr />
<!-- 修改 provide 共享的数据 -->
<div>
<button @click="setColorHandle">修改 provide的值 green</button>
</div>
</template>
<script setup>
import { inject, ref } from "vue";
// 通过 inject 注入读取共享数据
let color = inject("color");
// provide共享的数据、是可以修改的;(注意: 但不想让子组件修改数据, 可以在源数据中设置readonly! )
const setColorHandle = () =>{
color.value = 'yellow'
}
</script>
<style scoped>
.box {
width: 50px;
height: 50px;
border: 1px solid #ccc;
/* 定义 setup中的变量 */
background: v-bind(color);
}
</style>
实现效果