Vue 3 引入了 Composition API,提供了更多灵活的组件通信方式,以下是一些 Vue 3 中组件通信的代码示例:
1. Props 和 Emits
父组件向子组件传递数据使用 props,子组件通过 $emit 向父组件发送事件。
父组件:
<template>
<ChildComponent :parentMessage="message" @childEvent="handleChildEvent" />
</template>
<script setup>
import { ref } from 'vue';
import ChildComponent from './ChildComponent.vue';
const message = ref('Hello from parent!');
function handleChildEvent(data) {
console.log('Message from child:', data);
}
</script>
子组件:
<template>
<div @click="emitMessage">
{{ parentMessage }}
</div>
</template>
<script setup>
import { defineProps, defineEmits } from 'vue';
const props = defineProps({
parentMessage: String
});
const emit = defineEmits(['childEvent']);
function emitMessage() {
emit('childEvent', 'Hello from child!');
}
</script>
2. v-model
在 Vue 3 中,v-model 用于创建父子组件之间的双向绑定。
父组件:
<template>
<ChildComponent v-model:title="pageTitle" />
</template>
<script setup>
import { ref } from 'vue';
import ChildComponent from './ChildComponent.vue';
const pageTitle = ref('Initial Title');
</script>
子组件:
<template>
<input type="text" :value="title" @input="updateTitle" />
</template>
<script setup>
import { defineProps, defineEmits } from 'vue';
const props = defineProps({
title: String
});
const emit = defineEmits(['update:title']);
function updateTitle(event) {
emit('update:title', event.target.value);
}
</script>
3. provide / inject
允许祖先组件向所有子孙后代组件提供数据,不论层次结构有多深。
祖先组件:
<template>
<div>
<ChildComponent />
</div>
</template>
<script setup>
import { provide, ref } from 'vue';
import ChildComponent from './ChildComponent.vue';
const theme = ref('dark');
provide('theme', theme);
</script>
子孙组件:
<template>
<div>
The theme is: {{ theme }}
</div>
</template>
<script setup>
import { inject } from 'vue';
const theme = inject('theme');
</script>
4. Event Bus (使用第三方库如 mitt)
虽然 Vue 3 官方不推荐使用 EventBus,但可以通过第三方库如 mitt 实现。
创建 event bus:
// eventBus.js
import mitt from 'mitt';
const eventBus = mitt();
export default eventBus;
在组件中使用:
<template>
<button @click="emitEvent">Emit Event</button>
</template>
<script setup>
import eventBus from './eventBus.js';
function emitEvent() {
eventBus.emit('custom-event', 'Hello World!');
}
</script>
5. Refs 和 defineExpose
父组件可以通过 ref 获取子组件实例,并使用 defineExpose 在子组件中暴露数据或方法。
父组件:
<template>
<ChildComponent ref="child" />
</template>
<script setup>
import { ref } from 'vue';
import ChildComponent from './ChildComponent.vue';
const child = ref(null);
// 假设子组件暴露了 `exposedMethod`
child.value.exposedMethod();
</script>
子组件:
<script setup>
import { defineExpose, ref } from 'vue';
const exposedData = ref('Some data');
const exposedMethod = () => {
console.log('Exposed method called');
};
defineExpose({
exposedData,
exposedMethod
});
</script>