在 Vue 3 中,组件通信是构建复杂应用的关键部分。使用 <script setup>
语法糖可以让代码更加简洁和易读。以下是常见的组件通信方式,结合 <script setup>
语法糖进行讲解。
1. Props 和 Emit
这是 Vue 中最基础的父子组件通信方式。父组件通过 props
向子组件传递数据,子组件通过 emit
向父组件发送事件。
父组件
<template>
<ChildComponent :message="parentMessage" @update-message="handleUpdateMessage" />
</template>
<script setup>
import { ref } from 'vue';
import ChildComponent from './ChildComponent.vue';
const parentMessage = ref('Hello from parent');
const handleUpdateMessage = (newMessage) => {
parentMessage.value = newMessage;
};
</script>
子组件
<template>
<div>
<p>{{ message }}</p>
<button @click="updateMessage">Update Message</button>
</div>
</template>
<script setup>
const props = defineProps({
message: String
});
const emit = defineEmits(['update-message']);
const updateMessage = () => {
emit('update-message', 'New message from child');
};
</script>
2. Provide 和 Inject
provide
和inject
允许祖先组件向其所有子孙组件传递数据,而不需要通过props
层层传递。
祖先组件:
<template>
<ChildComponent />
</template>
<script setup>
import { provide, ref } from 'vue';
import ChildComponent from './ChildComponent.vue';
const message = ref('Hello from ancestor');
provide('message', message);
</script>
子孙组件:
<template>
<div>
<p>{{ injectedMessage }}</p>
</div>
</template>
<script setup>
import { inject } from 'vue';
const injectedMessage = inject('message');
</script>
3.Refs 和 parent/children
通过ref
可以直接访问子组件的实例,或者通过$parent
和$children
访问父组件或子组件的实例
父组件
<template>
<ChildComponent ref="child" />
<button @click="callChildMethod">Call Child Method</button>
</template>
<script setup>
import { ref } from 'vue';
import ChildComponent from './ChildComponent.vue';
const child = ref(null);
const callChildMethod = () => {
child.value.childMethod();
};
</script>
子组件
<template>
<div>
<p>Child Component</p>
</div>
</template>
<script setup>
const childMethod = () => {
console.log('Child method called');
};
defineExpose({
childMethod
});
</script>
4.Event Bus
Event Bus 是一种全局事件通信方式,适用于非父子组件之间的通信。
Event Bus:
import { createApp } from 'vue';
export const eventBus = createApp({});
组件A
<template>
<button @click="sendMessage">Send Message</button>
</template>
<script setup>
import { eventBus } from './eventBus';
const sendMessage = () => {
eventBus.emit('message', 'Hello from Component A');
};
</script>
组件B
<template>
<div>
<p>{{ message }}</p>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue';
import { eventBus } from './eventBus';
const message = ref('');
onMounted(() => {
eventBus.on('message', (newMessage) => {
message.value = newMessage;
});
});
</script>
5.Vuex
Vuex 是 Vue 的官方状态管理库,适用于大型应用中的全局状态管理。
Store:
import { createStore } from 'vuex';
export default createStore({
state: {
message: 'Hello from Vuex'
},
mutations: {
setMessage(state, newMessage) {
state.message = newMessage;
}
},
actions: {
updateMessage({ commit }, newMessage) {
commit('setMessage', newMessage);
}
}
});
组件A
<template>
<button @click="updateMessage">Update Message</button>
</template>
<script setup>
import { useStore } from 'vuex';
const store = useStore();
const updateMessage = () => {
store.dispatch('updateMessage', 'New message from Component A');
};
</script>
组件B
<template>
<div>
<p>{{ message }}</p>
</div>
</template>
<script setup>
import { computed } from 'vue';
import { useStore } from 'vuex';
const store = useStore();
const message = computed(() => store.state.message);
</script>
6.Pinia
Pinia 是 Vue 3 官方推荐的状态管理库,比 Vuex 更轻量且易于使用。它适合管理全局状态,类似于 Vuex,但语法更简洁。
- 安装
npm install pinia
创建 Store
// stores/messageStore.js
import { defineStore } from 'pinia';
export const useMessageStore = defineStore('message', {
state: () => ({
message: 'Hello from Pinia',
}),
actions: {
updateMessage(newMessage) {
this.message = newMessage;
},
},
});
组件A
<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>
组件B
<template>
<div>
<p>{{ messageStore.message }}</p>
</div>
</template>
<script setup>
import { useMessageStore } from './stores/messageStore';
const messageStore = useMessageStore();
</script>
总结
以上六种组件通信方式涵盖了 Vue 3 中常见的场景。根据具体需求选择合适的通信方式,可以大大提高代码的可维护性和可读性。