在Vue中,组件间通信主要有以下几种方式:
1.props / $attrs / $listeners (父子组件通信)
父组件向子组件传递数据主要通过props。子组件不能修改props原始值,但可以通过emit触发事件让父组件更新数据。
Vue2写法:
<!-- 父组件 -->
<template>
<ChildComponent :value="parentValue" @update-value="updateParentValue"/>
</template>
<script>
import ChildComponent from './ChildComponent.vue'
export default {
components: { ChildComponent },
data() {
return {
parentValue: '初始值'
}
},
methods: {
updateParentValue(newVal) {
this.parentValue = newVal;
}
}
}
</script>
<!-- 子组件 -->
<template>
<div>{{ value }}</div>
</template>
<script>
export default {
props: ['value'],
methods: {
updateValue() {
this.$emit('update-value', '新的值');
}
}
}
</script>
Vue3写法
<!-- 父组件 -->
<template>
<ChildComponent :value="parentValue" @update:value="updateParentValue"/>
</template>
<script setup>
import { ref } from 'vue';
import ChildComponent from './ChildComponent.vue';
let parentValue = ref('初始值');
function updateParentValue(newVal) {
parentValue.value = newVal;
}
</script>
<!-- 子组件 -->
<script setup>
import { defineProps, emit } from 'vue';
const props = defineProps({
value: String
});
function updateValue() {
emit('update:value', '新的值');
}
</script>
2.$refs (获取子组件实例)
如果需要直接操作子组件内部的属性或方法,可以使用ref并通过this.$refs获取子组件实例。
<!-- 父组件 -->
<template>
<ChildComponent ref="childRef"/>
</template>
<script>
export default {
mounted() {
console.log(this.$refs.childRef.internalValue);
}
}
</script>
<!-- 子组件 -->
<script>
export default {
data() {
return {
internalValue: '内部值'
}
}
}
</script>
3.Event Bus / mitt.js (全局事件总线)
创建一个事件中心进行跨层级组件通信
// eventBus.js
import mitt from 'mitt'; // 或自定义实现事件总线
export default mitt();
// 父组件
import EventBus from './eventBus.js';
EventBus.emit('message', '从父组件传递的数据');
// 子组件
import EventBus from './eventBus.js';
EventBus.on('message', (data) => {
console.log(data); // 输出:'从父组件传递的数据'
});
4.Vuex (状态管理库)
Vuex 提供了一个全局的状态树,便于多组件共享状态和管理。
// store.js
import { createStore } from 'vuex';
export default createStore({
state: {
sharedValue: ''
},
mutations: {
setSharedValue(state, newValue) {
state.sharedValue = newValue;
}
},
actions: {
updateSharedValue({ commit }, newValue) {
commit('setSharedValue', newValue);
}
},
getters: {
getSharedValue(state) {
return state.sharedValue;
}
}
});
// 组件内
computed: {
sharedValue() {
return this.$store.getters.getSharedValue;
}
},
methods: {
updateValue(newValue) {
this.$store.dispatch('updateSharedValue', newValue);
}
}
5.provide / inject (祖先与后代组件通信)
Vue2 和 Vue3 都支持 provide/inject 来实现祖先向后代注入依赖
//Vue2中使用
// 祖先组件(如 App.vue)
<script>
export default {
provide() {
return {
ancestorValue: '祖先值'
};
}
};
</script>
// 后代组件
<script>
export default {
inject: ['ancestorValue'],
created() {
console.log(this.ancestorValue); // 输出:'祖先值'
}
};
</script>
//在 Vue3 中,可以使用 setup 函数配合 provide 和 inject
// 祖先组件(如 App.vue)
<script setup>
import { provide } from 'vue';
provide('ancestorValue', '祖先值');
</script>
// 后代组件
<script setup>
import { inject } from 'vue';
const ancestorValue = inject('ancestorValue');
console.log(ancestorValue); // 输出:'祖先值'
</script>