vue3使用vue.js组件间通信
在 Vue 3 中,组件间通信是开发复杂应用的关键。Vue 3 提供了多种方式来实现组件间的数据传递和通信,以下是常见的组件间通信方式及其使用方法。
- Props 和 Events
这是 Vue 中最基础的组件通信方式,适用于父子组件之间的通信。
(1) Props
父组件通过 props 向子组件传递数据。
父组件传递数据
<!-- ParentComponent.vue -->
<template>
<ChildComponent :message="message" />
</template>
<script setup>
import { ref } from 'vue';
import ChildComponent from './ChildComponent.vue';
const message = ref('Hello from Parent!');
</script>
子组件接收数据
<!-- ChildComponent.vue -->
<template>
<div>{{ message }}</div>
</template>
<script setup>
defineProps({
message: String,
});
</script>
(2) Events
子组件通过 $emit 向父组件发送事件。
子组件发送事件
<!-- ChildComponent.vue -->
<template>
<button @click="sendMessage">Send Message</button>
</template>
<script setup>
const emit = defineEmits(['message']);
const sendMessage = () => {
emit('message', 'Hello from Child!');
};
</script>
父组件监听事件
<!-- ParentComponent.vue -->
<template>
<ChildComponent @message="handleMessage" />
</template>
<script setup>
const handleMessage = (message) => {
console.log(message); // 输出: Hello from Child!
};
</script>
v-model双向绑定
v-model 是 props 和 events 的语法糖,用于实现父子组件的双向绑定。
<!-- ParentComponent.vue -->
<template>
<ChildComponent v-model="message" />
</template>
<script setup>
import { ref } from 'vue';
import ChildComponent from './ChildComponent.vue';
const message = ref('Hello from Parent!');
</script>
<!-- ChildComponent.vue -->
<template>
<input :value="modelValue" @input="updateValue" />
</template>
<script setup>
defineProps({
modelValue: String,
});
const emit = defineEmits(['update:modelValue']);
const updateValue = (event) => {
emit('update:modelValue', event.target.value);
};
</script>
- Provide 和 Inject
provide 和 inject 用于跨层级组件通信,父组件通过 provide 提供数据,子孙组件通过 inject 注入数据。
<!-- ParentComponent.vue -->
<template>
<ChildComponent />
</template>
<script setup>
import { provide } from 'vue';
import ChildComponent from './ChildComponent.vue';
provide('message', 'Hello from Parent!');
</script>
<!-- ChildComponent.vue -->
<template>
<div>{{ message }}</div>
</template>
<script setup>
import { inject } from 'vue';
const message = inject('message');
</script>
- Event Bus(事件总线)
通过一个全局的事件总线实现任意组件间的通信。
使用 mitt 实现事件总线
// src/utils/eventBus.js
import mitt from 'mitt';
export const emitter = mitt();
<!-- ComponentA.vue -->
<template>
<button @click="sendMessage">Send Message</button>
</template>
<script setup>
import { emitter } from '@/utils/eventBus';
const sendMessage = () => {
emitter.emit('message', 'Hello from Component A!');
};
</script>
<!-- ComponentB.vue -->
<template>
<div>{{ message }}</div>
</template>
<script setup>
import { ref, onMounted, onUnmounted } from 'vue';
import { emitter } from '@/utils/eventBus';
const message = ref('');
const handleMessage = (data) => {
message.value = data;
};
onMounted(() => {
emitter.on('message', handleMessage);
});
onUnmounted(() => {
emitter.off('message', handleMessage);
});
</script>
- Vuex/Pinia(状态管理)
对于复杂的应用,可以使用 Vuex 或 Pinia 进行全局状态管理。
// src/stores/messageStore.js
import { defineStore } from 'pinia';
export const useMessageStore = defineStore('message', {
state: () => ({
message: 'Hello from Store!',
}),
actions: {
updateMessage(newMessage) {
this.message = newMessage;
},
},
});
<!-- ComponentA.vue -->
<template>
<button @click="updateMessage">Update Message</button>
</template>
<script setup>
import { useMessageStore } from '@/stores/messageStore';
const messageStore = useMessageStore();
const updateMessage = () => {
messageStore.updateMessage('New Message from Component A!');
};
</script>
<!-- ComponentB.vue -->
<template>
<div>{{ messageStore.message }}</div>
</template>
<script setup>
import { useMessageStore } from '@/stores/messageStore';
const messageStore = useMessageStore();
</script>
ref和expose
父组件通过 ref 获取子组件实例,并调用子组件的方法或访问其属性。
<!-- ParentComponent.vue -->
<template>
<ChildComponent ref="childRef" />
<button @click="callChildMethod">Call Child Method</button>
</template>
<script setup>
import { ref } from 'vue';
import ChildComponent from './ChildComponent.vue';
const childRef = ref(null);
const callChildMethod = () => {
childRef.value.childMethod();
};
</script>
<!-- ChildComponent.vue -->
<template>
<div>Child Component</div>
</template>
<script setup>
const childMethod = () => {
console.log('Child method called!');
};
defineExpose({
childMethod,
});
</script>
总结
Vue 3 提供了多种组件间通信的方式,适用于不同的场景:
-
父子组件通信:
props和events、v-model。 -
跨层级通信:
provide和inject。 -
任意组件通信:事件总线(如
mitt)。 -
全局状态管理:Vuex 或 Pinia。
-
访问子组件实例:
ref和expose。
根据具体需求选择合适的通信方式,可以提升代码的可维护性和开发效率。
更多vue相关插件及后台管理模板可访问vue admin reference,代码详情请访问github