在 Vue 应用中,组件间的通信是一个常见的需求。Vue 提供了多种机制来实现不同组件之间的数据共享和通信。以下是一些常用的组件通信方式,以及使用 Vue 3 setup
语法糖的示例代码。
1. Props 和 Emits
Props 和 emits 是父子组件通信的传统方式。父组件通过 props
向子组件传递数据,子组件通过 emits
发送事件给父组件。
示例代码:
父组件:
<template>
<ChildComponent :parent-msg="message" @updateMessage="updateMessage" />
</template>
<script setup>
import { ref } from 'vue';
import ChildComponent from './ChildComponent.vue';
const message = ref('Hello from parent');
const updateMessage = (newMessage) => {
message.value = newMessage;
};
</script>
子组件:
<template>
<div>
<p>{{ parentMsg }}</p>
<button @click="emitMessage">Change Message</button>
</div>
</template>
<script setup>
import { defineProps, defineEmits } from 'vue';
const props = defineProps(['parentMsg']);
const emit = defineEmits(['updateMessage']);
const emitMessage = () => {
emit('updateMessage', 'Updated message from child');
};
</script>
2. Provide 和 Inject
provide
和 inject
用于跨组件层级的通信,允许祖先组件向其所有子孙组件提供数据,而不论组件层次有多深。
示例代码:
祖先组件:
<template>
<div>
<ChildComponent />
</div>
</template>
<script setup>
import { provide } from 'vue';
import ChildComponent from './ChildComponent.vue';
provide('theme', 'dark');
</script>
子孙组件:
<template>
<div :class="theme">Child Component</div>
</template>
<script setup>
import { inject } from 'vue';
const theme = inject('theme');
</script>
<style>
.dark {
background-color: black;
color: white;
}
</style>
3. Refs
Refs
可以用来访问子组件的实例和其方法,适用于父子组件之间的通信。
示例代码:
父组件:
<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 = () => {
if (childRef.value) {
childRef.value.childMethod();
}
};
</script>
子组件:
<script setup>
const childMethod = () => {
alert('Method called from parent');
};
export {
childMethod
};
</script>
4. Event Bus
虽然 Vue 3 不再推荐使用 Event Bus,但它仍然是一种实现非父子组件通信的方式。
示例代码:
创建一个 Event Bus:
// eventBus.js
import { reactive, readonly } from 'vue';
export const eventBus = reactive(new Vue());
export function useEventBus() {
return readonly(eventBus);
}
组件 A:
<script setup>
import { eventBus } from './eventBus';
eventBus.$on('custom-event', (data) => {
console.log(data);
});
</script>
组件 B:
<script setup>
import { eventBus } from './eventBus';
function emitEvent() {
eventBus.$emit('custom-event', 'Hello from Component B');
}
</script>
<template>
<button @click="emitEvent">Emit Event</button>
</template>
5. Vuex
对于大型应用,Vuex 是官方的状态管理模式和库,它提供了一个中央存储来管理所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
示例代码:
// store/index.js
import { createStore } from 'vuex';
export default createStore({
state: {
count: 0
},
mutations: {
increment(state) {
state.count++;
}
}
});
在组件中使用:
<template>
<button @click="increment">Count is: {{ count }}</button>
</template>
<script setup>
import { useStore } from 'vuex';
const store = useStore();
function increment() {
store.commit('increment');
}
const count = computed(() => store.state.count);
</script>
6. Provide/Inject with reactive
or ref
在 Vue 3 中,你还可以使用 reactive
或 ref
与 provide
和 inject
结合使用,来共享响应式状态。
示例代码:
祖先组件:
<template>
<div>
<ChildComponent />
</div>
</template>
<script setup>
import { reactive, provide } from 'vue';
import ChildComponent from './ChildComponent.vue';
const theme = reactive({ color: 'dark' });
provide('theme', theme);
</script>
子孙组件:
<template>
<div :class="theme.color">Child Component</div>
</template>
<script setup>
import { inject } from 'vue';
const theme = inject('theme');
</script>
<style>
.dark {
background-color: black;
color: white;
}
</style>
总结
Vue 提供了多种组件通信的方式,包括 Props 和 Emits、Provide 和 Inject、Refs、Event Bus、Vuex 等。选择哪种方式取决于你的具体需求和组件之间的关系。通过合理使用这些通信方式,你可以创建更加动态和交互性强的 Vue 应用程序。