Provide / Inject
通常,当我们需要从父组件向子组件传递数据时,我们使用 props。想象一下这样的结构:有一些深度嵌套的组件,而深层的子组件只需要父组件的部分内容。在这种情况下,如果仍然将 prop 沿着组件链逐级传递下去,可能会很麻烦。
官网的解释很让人疑惑,那我翻译下这几句话:
provide 可以在祖先组件中指定我们想要提供给后代组件的数据或方法,而在任何后代组件中,我们都可以使用 inject 来接收 provide 提供的数据或方法。
代码示例
额外的知识点
// let color = inject<Ref<string>>("color", ref("red")); // 1.给一个red默认值
let change = () => {
// color?.value = "blue"; // 不能使用可选操作符? 有二种方式处理
color!.value = "blue"; // 2.非空断言 !
};
let colorVal = ref<string>("red");
background: v-bind(
colorVal
); // 在vue3中可以获取js中的变量,background-color样式不生效
顶层组件(爷爷级)
<template>
<!-- 可参考这个文章 -->
<h3>Angular依赖注入 是通过IOC控制反转和依赖注入(DI)</h3>
<h3>vue依赖注入provide和inject 是通过原型链</h3>
<div class="text">爷爷级别</div>
<h6>
当用户点击一个单选按钮时,它就会被选中,其他同名的单选按钮就不会被选中。
</h6>
<label>
<input
type="radio"
v-model="colorVal"
value="yellow"
name="color"
/>
黄色
</label>
<label>
<input
type="radio"
v-model="colorVal"
value="blue"
name="color"
/>
蓝色</label
>
<div class="box"></div>
<A></A>
</template>
<script setup lang="ts">
import {
ref,
reactive,
watch,
provide,
readonly,
} from "vue";
import A from "./components/fifteen_A.vue";
let colorVal = ref<string>("red");
// provide("color", readonly(colorVal)); // key value readonly约束子组件修改值
provide("color", colorVal);
watch(
() => colorVal.value,
(newVal) => {
console.log(newVal);
}
);
</script>
<style lang="less" scoped>
.text {
color: red;
}
.box {
width: 50px;
height: 50px;
border: 1px solid #ccc;
background: v-bind(
colorVal
); // 在vue3中可以获取js中的变量,background-color样式不生效
}
</style>
父级组件A
<template>
<div class="text">父亲级别</div>
<div class="box"></div>
<B></B>
</template>
<script setup lang="ts">
import { ref, reactive, watch, inject } from "vue";
import B from "./fifteen_B.vue";
import type { Ref } from "vue";
//与注入provide的key保持一致,由于color推断出来的类型是unkown,由于传入的是ref,故这里需要引入Ref的泛型,再接收泛型string
// let color = inject("color");
let color = inject<Ref<string>>("color"); // 此时color推断出来的类型是: Ref<string> | undefined
</script>
<style lang="less" scoped>
.text {
color: red;
}
.box {
width: 50px;
height: 50px;
border: 1px solid #ccc;
background: v-bind(
color
); // 在vue3中可以获取js中的变量,background-color样式不生效
}
</style>
孙子组件B
<template>
<div class="text">孙子级别</div>
<button @click="change">
在子组件中修改provide传入的值为blue
</button>
<div class="box"></div>
</template>
<script setup lang="ts">
import { ref, reactive, watch, inject } from "vue";
import type { Ref } from "vue";
let color = inject("color");
// let color = inject<Ref<string>>("color", ref("red")); // 1.给一个red默认值
let change = () => {
// color?.value = "blue"; // 不能使用可选操作符? 有二种方式处理
color!.value = "blue"; // 2.非空断言 !
};
</script>
<style lang="less" scoped>
.text {
color: red;
}
.box {
width: 50px;
height: 50px;
border: 1px solid #ccc;
background: v-bind(
color
); // 在vue3中可以获取js中的变量,background-color样式不生效
}
</style>