vue父子通讯优雅实现
Vue 父子组件通信的优雅实现方案
Props 与事件传递
父组件通过 props 向子组件传递数据,子组件通过 $emit 触发事件通知父组件。这是 Vue 官方推荐的基础通信方式。
父组件示例:
<template>
<ChildComponent :message="parentMessage" @update="handleUpdate"/>
</template>
<script>
export default {
data() {
return {
parentMessage: 'Hello from parent'
}
},
methods: {
handleUpdate(newValue) {
this.parentMessage = newValue
}
}
}
</script>
子组件示例:
<template>
<button @click="notifyParent">Click me</button>
</template>
<script>
export default {
props: ['message'],
methods: {
notifyParent() {
this.$emit('update', 'New value from child')
}
}
}
</script>
v-model 语法糖
对于表单类组件,可以使用 v-model 实现双向绑定,本质上是 props 和事件的语法糖。
父组件:
<ChildComponent v-model="parentValue"/>
子组件:
<template>
<input :value="value" @input="$emit('input', $event.target.value)"/>
</template>
<script>
export default {
props: ['value']
}
</script>
.sync 修饰符
需要双向绑定时,可以使用 .sync 修饰符简化代码。
父组件:
<ChildComponent :title.sync="pageTitle"/>
子组件:
<script>
export default {
props: ['title'],
methods: {
updateTitle() {
this.$emit('update:title', 'New Title')
}
}
}
</script>
Provide/Inject
跨层级组件通信可以使用这对 API,适用于深层嵌套组件场景。
祖先组件:
export default {
provide() {
return {
theme: 'dark'
}
}
}
后代组件:
export default {
inject: ['theme']
}
事件总线
对于非父子关系的组件,可以创建中央事件总线。
创建事件总线:
// eventBus.js
import Vue from 'vue'
export const EventBus = new Vue()
组件A发送事件:
EventBus.$emit('event-name', payload)
组件B接收事件:
EventBus.$on('event-name', payload => {
// 处理逻辑
})
Vuex 状态管理
对于复杂应用,使用 Vuex 集中管理状态是最佳实践。
store 定义:
export default new Vuex.Store({
state: {
count: 0
},
mutations: {
increment(state) {
state.count++
}
}
})
组件中使用:
this.$store.commit('increment')
console.log(this.$store.state.count)
作用域插槽
当需要父组件控制子组件内部部分内容的渲染时,可以使用作用域插槽。
子组件:
<template>
<div>
<slot :user="user"></slot>
</div>
</template>
<script>
export default {
data() {
return {
user: {
name: 'John'
}
}
}
}
</script>
父组件:
<ChildComponent>
<template v-slot:default="slotProps">
{{ slotProps.user.name }}
</template>
</ChildComponent>
$refs 引用
在需要直接访问子组件实例时可以使用,但应谨慎使用以避免过度耦合。
父组件:
<ChildComponent ref="child"/>
访问子组件:
this.$refs.child.childMethod()
每种方案都有其适用场景,应根据具体需求选择最合适的通信方式。简单场景优先使用 props/events,复杂场景考虑 Vuex 或事件总线。







