Vue2 组件通信全解析
在 Vue2 中,组件之间的通信是构建复杂应用的关键。本文将详细介绍 Vue2 中各种组件通信方式,包括父子组件通信、任意组件通信等,并提供代码示例。
1. 父组件向子组件传值:props
props 是 Vue 中最基础的父子组件通信方式,父组件通过 props 向子组件传递数据。
html
<!-- 父组件 Parent.vue -->
<template>
<div>
<h2>父组件</h2>
<Child :message="parentMessage" :userInfo="userData" />
</div>
</template>
<script>
import Child from './Child.vue'
export default {
components: { Child },
data() {
return {
parentMessage: 'Hello from Parent',
userData: {
name: 'John',
age: 30
}
}
}
}
</script>
html
<!-- 子组件 Child.vue -->
<template>
<div>
<h3>子组件</h3>
<p>父组件消息: {{ message }}</p>
<p>用户信息: {{ userInfo.name }} - {{ userInfo.age }}</p>
</div>
</template>
<script>
export default {
props: {
message: {
type: String,
required: true
},
userInfo: {
type: Object,
default: () => ({})
}
}
}
</script>
2. 子组件向父组件传值
方式一:使用自定义事件
html
<!-- 父组件 Parent.vue -->
<template>
<div>
<h2>父组件</h2>
<Child @send-data="handleData" />
<p>来自子组件的数据: {{ childData }}</p>
</div>
</template>
<script>
import Child from './Child.vue'
export default {
components: { Child },
data() {
return {
childData: ''
}
},
methods: {
handleData(data) {
this.childData = data
}
}
}
</script>
html
<!-- 子组件 Child.vue -->
<template>
<div>
<h3>子组件</h3>
<button @click="sendDataToParent">发送数据给父组件</button>
</div>
</template>
<script>
export default {
methods: {
sendDataToParent() {
this.$emit('send-data', 'Data from Child')
}
}
}
</script>
方式二:使用 ref
html
<!-- 父组件 Parent.vue -->
<template>
<div>
<h2>父组件</h2>
<Child ref="childRef" />
<p>来自子组件的数据: {{ childData }}</p>
</div>
</template>
<script>
import Child from './Child.vue'
export default {
components: { Child },
data() {
return {
childData: ''
}
},
mounted() {
this.$refs.childRef.$on('custom-event', (data) => {
this.childData = data
})
},
beforeDestroy() {
// 避免内存泄漏
this.$refs.childRef.$off('custom-event')
}
}
</script>
html
<!-- 子组件 Child.vue -->
<template>
<div>
<h3>子组件</h3>
<button @click="triggerCustomEvent">触发自定义事件</button>
</div>
</template>
<script>
export default {
methods: {
triggerCustomEvent() {
this.$emit('custom-event', 'Custom event data')
}
}
}
</script>
3. 任意组件间通信
方式一:Vuex 状态管理
首先安装 Vuex:
bash
npm install vuex
js
// store.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
sharedData: 'Initial data from Vuex'
},
mutations: {
updateSharedData(state, payload) {
state.sharedData = payload
}
},
actions: {
updateData({ commit }, data) {
commit('updateSharedData', data)
}
},
getters: {
getSharedData: state => state.sharedData
}
})
html
<!-- 组件A ComponentA.vue -->
<template>
<div>
<h3>组件A</h3>
<p>共享数据: {{ sharedData }}</p>
<button @click="updateData">更新数据</button>
</div>
</template>
<script>
import { mapGetters, mapActions } from 'vuex'
export default {
computed: {
...mapGetters(['getSharedData']),
sharedData() {
return this.getSharedData
}
},
methods: {
...mapActions(['updateData']),
updateData() {
this.updateData('Updated from Component A')
}
}
}
</script>
html
<!-- 组件B ComponentB.vue -->
<template>
<div>
<h3>组件B</h3>
<p>共享数据: {{ sharedData }}</p>
</div>
</template>
<script>
import { mapGetters } from 'vuex'
export default {
computed: {
...mapGetters(['getSharedData']),
sharedData() {
return this.getSharedData
}
}
}
</script>
方式二:全局事件总线
js
// main.js
import Vue from 'vue'
import App from './App.vue'
// 创建事件总线
Vue.prototype.$eventBus = new Vue()
new Vue({
render: h => h(App)
}).$mount('#app')
html
<!-- 发送组件 Sender.vue -->
<template>
<div>
<h3>发送组件</h3>
<button @click="sendMessage">发送全局消息</button>
</div>
</template>
<script>
export default {
methods: {
sendMessage() {
this.$eventBus.$emit('global-event', 'Message from Sender')
}
}
}
</script>
html
<!-- 接收组件 Receiver.vue -->
<template>
<div>
<h3>接收组件</h3>
<p>全局消息: {{ globalMessage }}</p>
</div>
</template>
<script>
export default {
data() {
return {
globalMessage: ''
}
},
mounted() {
this.$eventBus.$on('global-event', (msg) => {
this.globalMessage = msg
})
},
beforeDestroy() {
// 避免内存泄漏
this.$eventBus.$off('global-event')
}
}
</script>
总结
-
父子组件通信:
- 父传子:使用 props
- 子传父:使用自定义事件(
$emit)或 ref
-
任意组件通信:
- Vuex:适合大型应用,集中管理状态
- 全局事件总线:适合小型应用,简单直接
-
最佳实践:
- 简单父子通信使用 props 和
$emit - 复杂应用或兄弟组件通信使用 Vuex
- 小型项目可以考虑事件总线,但要注意及时销毁事件监听避免内存泄漏
- 简单父子通信使用 props 和
选择哪种通信方式取决于应用规模和组件关系的复杂度。对于简单应用,props 和自定义事件通常足够;对于大型应用,Vuex 提供了更可预测的状态管理。