概述
在 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>