Vue3 通过privide和inject进行组件复杂通信
在项目中,一些简单的父子通信可以通过prop和emit的方式实现,但通信层次较深时或者场景较为复杂时,逐级prop的方式显得非常愚蠢,可以通过provide和inject的方式实现组件通信。
场景:子组件A需要与同级子组件B进行通信
父组件
<template>
<div class="father_container">
<Son1 ref="son1" />
<Son2 ref="son2" />
</div>
</template>
<script lang="ts">
import { defineComponent, ref, provide } from "vue";
import Son1 from "./Son1.vue";
import Son2 from "./Son2.vue";
// 定义CompRef为一个函数
export type CompRef = () => {
son1: InstanceType<typeof Son1>;
son2: InstanceType<typeof Son2>;
};
export default defineComponent({
name: "Father",
components: {
Son1,
Son2,
},
setup() {
const son1 = ref();
const son2 = ref();
// provide compRef,为一个函数
provide("compRef", () => {
return { son1: son1.value, son2: son2.value }
});
return {
son1,
son2,
};
},
});
</script>
<style lang="scss" scoped></style>
子组件A
<template>
<div class="son1-container">
<el-button @click="handleClick">click</el-button>
<el-button @click="handleChangeOther">改变son2</el-button>
<el-input v-model="name"></el-input>
</div>
</template>
<script lang="ts">
import { defineComponent, ref, inject, defineExpose } from "vue";
import type { CompRef } from "./Father.vue";
export default defineComponent({
name: "Son1",
setup() {
const compRef = inject("compRef") as CompRef;
const name = ref("son1");
const handleClick = () => {
name.value = name.value + "more_";
};
const handleChangeOther = () => {
console.log('ref',compRef)
compRef().son2.handleClick();
};
defineExpose({
handleClick
})
return {
name,
handleClick,
handleChangeOther
};
},
});
</script>
<style lang="scss" scoped></style>
子组件B
<template>
<div class="son2-container">
<el-button @click="handleClick">click</el-button>
<el-button @click="handleChangeOther">改变son1</el-button>
<el-input v-model="name"></el-input>
</div>
</template>
<script lang="ts">
import { defineComponent, ref, inject, defineExpose } from "vue";
import type { CompRef } from "./Father.vue";
export default defineComponent({
name: "Son2",
setup() {
const name = ref("son2");
const compRef = inject('compRef') as CompRef;
const handleClick = () => {
name.value = name.value + "more_";
};
const handleChangeOther = () => {
compRef().son1.handleClick();
};
defineExpose({
handleClick
})
return {
name,
handleClick,
handleChangeOther
};
},
});
</script>
<style lang="scss" scoped></style>