provide/inject的使用
一般我们父子组件传值是通过props传值,但是如果层级特别深的话,假如仅仅只有最里面一层的子组件需要最外层父组件中的某一个值的话,props传值的话就要一层一层的往外传,子组件修改还要一层一层的往外通知,特别繁琐,也挺烦人的,就一个值传递了整个组件链,如果遇到这种情况我们就可以使用provide和inject。父组件作为其所有子组件的依赖项提供数据,不用管组件层级有多深。
父组件有一个provide选项提供数据,子组件有一个inject选项来使用数据。
1. 基础使用:
在父组件中提供数据:
const app = Vue.createApp({});
app.component('Parent', {
provide: {
user: 'Sunny'
}
});
在子组件中使用数据:
app.component('Child', {
inject: ['user'],
created() {
console.log(this.user); // 输出 Sunny
}
});
如果提供的数据为父组件中的组件实例属性时,这样则不起作用,要想访问组件实例属性值传给子组件,需要将provide转换为返回对象的函数.比如:
app.component('Parent', {
data() {
return {
name: 'Sunny'
}
},
provide() {
return {
user: this.name
}
}
});
这样实现就不用担心可能更改/删除子组件所依赖的某些东西,组件传值看起来更加明确。父组件不需要知道哪些子组件需要使用他提供的实例属性,子组件也不用知道 inject的属性来自哪里。
2. 处理响应式数据:
如果对于一些更改了provide中提供的属性值,这个值是不会反映到子组件中的,因为在默认情况下provide/inject绑定不是被动绑定,我们可以通过将ref或者reactive对象传递给provide来更改此行为。
在这里我们可以给name分配一个computed属性。
app.component('Parent', {
data() {
return {
name: 'Sunny'
}
},
provide() {
return {
user: Vue.computed(() => this.name)
}
}
});
在setup中使用provide时,首先从vue中导入provide。provide可以传两个参数值:name:类型 value:值
// 父组件:
<template>
<child1 :name="name" />
<button @click="changeName">更改name值</button>
</template>
<script>
import { provide, ref } from "vue";
import Child1 from "./modules/Child1";
export default {
name: "Provide",
setup() {
let name = ref("child-child-child-child-child-child");
let changeName = () => {
name.value = `this is a change name!!!${Math.random()}`;
};
provide("name", name);
return {
name,
changeName,
};
},
components: {
Child1,
},
}
</script>
子组件使用inject注入:有两个参数:要注入的属性名称,一个默认值(可选)
// 子组件:
<template>
<div>child4</div>
<div>{{ name }}</div>
</template>
<script>
import { inject } from "vue";
export default {
name: "Child4",
setup() {
const name = inject("name");
return {
name
};
}
};
</script>