通常,当我们需要将数据从父组件传递到子组件时,我们使用 props。想象一下这样的结构:你有一些深嵌套的组件,而你只需要来自深嵌套子组件中父组件的某些内容。在这种情况下,你仍然需要将 prop 传递到整个组件链中,这可能会很烦人。对于这种情况,我们可以使用 provide 和 inject 对。父组件可以作为其所有子组件的依赖项提供程序,而不管组件层次结构有多深。这个特性有两个部分:父组件有一个 provide 选项来提供数据,子组件有一个 inject 选项来开始使用这个数据。
上面这段话也比较好理解,就是通常数据传递一层,我们使用prop就可以很好的解决,如果传递多层,再使用prop就不是很好的方案,这时需要provide和inject,多数情况下,provide会和inject一起使用,又叫“依赖注入”。
“依赖注入”主要是解决父子组件传值“props逐级传递”问题。所以,provide/inject的作用就是组件间的传值。
vue2中的基本用法:
1.provide
provide 是一个对象或是返回一个对象的函数。
写在祖先组件中,用于提供给子组件可以注入的值。组件的关系为a-b-c-d
在a组件中将参数num进行传递
export default {
components: { BCom },
data() {
return {
num: 2,
};
},
provide() {
return {
num: this.num,
};
},
};
2.inject
inject为:一个数组,数组元素为注入的变量
一个对象,key为注入的变量,value为一个包含form和default的对象
num: {
from: 'num',
default: '20'
}
在d组件中接收注入的变量
写法一:
export default {
inject: ["num"],
};
写法二:
export default {
inject: {
num: {
form: "num",
default: 20,
},
},
};
num 不是响应式的,如何成为响应式?
1.方法一:函数方法
a组件:
<template>
<div style="width: 600px; height: 600px; background-color: darkgreen">
我是组件a
<h4>{{ num }}</h4>
<button @click="add">+100</button>
<BCom></BCom>
</div>
</template>
<script>
import BCom from "./b-com.vue";
export default {
components: { BCom },
data() {
return {
num: 2,
};
},
provide() {
return {
num: () => this.num,
};
},
methods: {
add() {
this.num = this.num + 100;
},
},
};
</script>
b组件
<template>
<div
style="
width: 300px;
height: 300px;
background-color: bisque;
"
>
我是组件d
<h4>{{ this.num() }}</h4>
</div>
</template>
<script>
export default {
inject: {
num: {
form: "num",
default: () => {},
},
},
};
</script>
2.方法二:传递this
a组件
<template>
<div style="width: 600px; height: 600px; background-color: darkgreen">
我是组件a
<h4>{{ num }}</h4>
<button @click="add">+100</button>
<BCom></BCom>
</div>
</template>
<script>
import BCom from "./b-com.vue";
export default {
components: { BCom },
data() {
return {
num: 2,
};
},
provide() {
return {
AThis: this,
};
},
methods: {
add() {
this.num = this.num + 100;
},
},
};
</script>
d组件
<template>
<div
style="
width: 300px;
height: 300px;
background-color: bisque;
"
>
我是组件d
<h4>{{ this.AThis.num }}</h4>
</div>
</template>
<script>
export default {
inject: {
AThis: {
form: "AThis",
default() {
return {};
},
},
},
};
</script>
vue3中的基本用法:
provide() 接受两个参数:第一个参数是要注入的 key,可以是一个字符串或者一个 symbol,第二个参数是要注入的值。
<script setup>
import { ref, provide } from 'vue'
// 提供静态值
provide('num')
// 提供响应式的值
const count = ref(0)
provide('count', count)
</script>
inject:
第一个参数是注入的 key。
Vue 会遍历父组件链,通过匹配 key 来确定所提供的值。如果父组件链上多个组件对同一个 key 提供了值,那么离得更近的组件将会“覆盖”链上更远的组件所提供的值。如果没有能通过 key 匹配到值,inject() 将返回 undefined,除非提供了一个默认值。
第二个参数是可选的,即在没有匹配到 key 时使用的默认值。它也可以是一个工厂函数,用来返回某些创建起来比较复杂的值。如果默认值本身就是一个函数,那么你必须将 false 作为第三个参数传入,表明这个函数就是默认值,而不是一个工厂函数。
<script setup>
import { inject } from 'vue'
// 注入值的默认方式
const num= inject('num')
// 注入响应式的值
const count = inject('count')
// 注入一个值,若为空则使用提供的默认值
const bar = inject('foo', 'default value')
// 注入一个值,若为空则使用提供的工厂函数
const baz = inject('foo', () => new Map())
// 注入时为了表明提供的默认值是个函数,需要传入第三个参数
const fn = inject('function', () => {}, false)
</script>