概述
在 Vue 中,当父组件向子组件传递数据时,会使用 Props。但是如果需要向更深层级的组件传递数据的话使用 Props 逐级传递会变得非常繁琐。
而 provide / inject 是一种高级组件通讯方式, 它可以解决 Props 逐级传递的问题。一个父组件通过 provide 注册依赖,为其所有的后代组件使用,其任何后代组件都通过 inject 注入依赖进行使用。
provide/inject
provide
provide 可以是个 对象 或是 函数。
对象类型:
provide: {
message: "Hello,Vue2!",
}
- 对象类型的
provide访问不到this实例。
export default {
provide: {
message: this.message,
},
data() {
return {
message: "Hello,Vue2!",
};
},
};
- 上面的例子会报错,如果想要访问组件实例,可以将
provide定义为函数返回一个对象的方式。
函数类型:
provide() {
return {
message: "Hello,Vue2!"
};
},
provide函数可以访问到当前组件实例的this。
export default {
provide() {
return {
message: this.message
};
},
data() {
return {
message: "Hello,Vue2!",
};
},
};
inject
inject 可以是个 数组 或 对象。
在 Vue2.2.1 或更高版本时,inject 注入的值会在 props 和 data 初始化之前。
数组类型:
- 数组中的每一个元素表示需要注入的属性名。
inject: ["message"]
- 注入父元素提供的依赖
message,注入后可以直接this.message进行访问。
对象类型:
-
对象类型下有两个选项,分别是:
from:注入的属性名。default:默认值。
-
使用方式:
inject: {
// 写法1:
myUser: { // 从祖先组件中注入的 user 名会被重写成 myUser 作用在当前注入属性的组件实例中。
from: "user", // 注入的属性名
default: () => ({}), // 默认值
},
// 写法2:
user: { // 注入的属性名
default: () => ({}), // 默认值
},
},
使用注意
provide和inject绑定并不是可响应的。这是刻意为之的。然而,如果你传入了一个可监听的对象,那么其对象的 property 还是可响应的。
父:
<template>
<div>
<p>父-user:{{ user.name }}</p>
<p>父-list:{{ list }}</p>
<p>父-message:{{ message }}</p>
<br />
<Child />
</div>
</template>
<script>
import Child from "@/components/Child.vue";
export default {
components: {
Child,
},
provide() {
return {
user: this.user, // 会被刷新,传入的是可监听对象
list: this.list, // 会被刷新,传入的是可监听对象
message: this.message, // 父元素 message 改变,子元素的 message 并不会被刷新,基本数据类型不具备可响应。
};
},
data() {
return {
user: {
name: "张三",
},
message: "",
list: [1, 2, 3, 4],
};
},
mounted() {
setTimeout(() => {
this.user.name = "李四";
this.list.push(5);
this.message = "值发生改变";
}, 2000);
},
};
</script>
子:
<template>
<div>
<p>子-user:{{ user.name }}</p>
<p>子-list:{{ list }}</p>
<p>子-message:{{ message }}</p>
</div>
</template>
<script>
export default {
inject: {
user: {
default: () => ({}),
},
list: {
default: () => [],
},
message: {
default: "",
},
},
};
</script>