vue父子通讯优雅实现
Vue 父子组件通信的优雅实现方式
1. Props 传递数据
父组件通过 props 向子组件传递数据,子组件通过声明 props 接收数据。这种方式适用于父组件向子组件传递静态或动态数据。
父组件代码示例:
<template>
<child-component :message="parentMessage" />
</template>
<script>
import ChildComponent from './ChildComponent.vue';
export default {
components: { ChildComponent },
data() {
return {
parentMessage: 'Hello from parent'
};
}
};
</script>
子组件代码示例:
<template>
<div>{{ message }}</div>
</template>
<script>
export default {
props: {
message: {
type: String,
required: true
}
}
};
</script>
2. 自定义事件通信
子组件通过 $emit 触发自定义事件,父组件通过 v-on 监听事件并处理。这种方式适用于子组件向父组件传递数据或触发父组件方法。
子组件代码示例:
<template>
<button @click="sendMessage">Send Message</button>
</template>
<script>
export default {
methods: {
sendMessage() {
this.$emit('message-sent', 'Hello from child');
}
}
};
</script>
父组件代码示例:
<template>
<child-component @message-sent="handleMessage" />
</template>
<script>
import ChildComponent from './ChildComponent.vue';
export default {
components: { ChildComponent },
methods: {
handleMessage(msg) {
console.log(msg); // 输出: Hello from child
}
}
};
</script>
3. 使用 v-model 实现双向绑定
通过 v-model 实现父子组件数据的双向绑定,适用于表单类组件。子组件需要声明 model 选项并处理 input 事件。
子组件代码示例:
<template>
<input :value="value" @input="$emit('input', $event.target.value)" />
</template>
<script>
export default {
props: ['value']
};
</script>
父组件代码示例:
<template>
<child-component v-model="message" />
</template>
<script>
import ChildComponent from './ChildComponent.vue';
export default {
components: { ChildComponent },
data() {
return {
message: ''
};
}
};
</script>
4. 使用 .sync 修饰符
.sync 修饰符提供了一种双向绑定的简化写法,适用于需要同步多个 props 的情况。
父组件代码示例:
<template>
<child-component :title.sync="pageTitle" />
</template>
<script>
import ChildComponent from './ChildComponent.vue';
export default {
components: { ChildComponent },
data() {
return {
pageTitle: 'Default Title'
};
}
};
</script>
子组件代码示例:

<template>
<button @click="updateTitle">Update Title</button>
</template>
<script>
export default {
props: ['title'],
methods: {
updateTitle() {
this.$emit('update:title', 'New Title');
}
}
};
</script>
5. 使用 Provide/Inject
跨层级组件通信可以通过 provide 和 inject 实现,适用于深层嵌套组件场景。
祖先组件代码示例:
<script>
export default {
provide() {
return {
theme: 'dark'
};
}
};
</script>
后代组件代码示例:
<script>
export default {
inject: ['theme'],
created() {
console.log(this.theme); // 输出: dark
}
};
</script>
6. 使用事件总线
对于非父子关系的组件通信,可以创建事件总线实现全局事件监听和触发。
创建事件总线:
// event-bus.js
import Vue from 'vue';
export const EventBus = new Vue();
组件A触发事件:

import { EventBus } from './event-bus.js';
EventBus.$emit('custom-event', 'some data');
组件B监听事件:
import { EventBus } from './event-bus.js';
EventBus.$on('custom-event', data => {
console.log(data); // 输出: some data
});
7. 使用 Vuex 状态管理
对于复杂应用状态管理,使用 Vuex 是更优雅的解决方案,可以集中管理所有组件的状态。
Vuex store 示例:
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
export default new Vuex.Store({
state: {
count: 0
},
mutations: {
increment(state) {
state.count++;
}
},
actions: {
increment({ commit }) {
commit('increment');
}
}
});
组件中使用:
<template>
<div>{{ $store.state.count }}</div>
<button @click="$store.dispatch('increment')">Increment</button>
</template>
8. 使用 $refs 直接访问组件
父组件可以通过 $refs 直接访问子组件实例,适用于需要直接调用子组件方法的场景。
父组件代码示例:
<template>
<child-component ref="child" />
<button @click="callChildMethod">Call Child Method</button>
</template>
<script>
import ChildComponent from './ChildComponent.vue';
export default {
components: { ChildComponent },
methods: {
callChildMethod() {
this.$refs.child.childMethod();
}
}
};
</script>
子组件代码示例:
<script>
export default {
methods: {
childMethod() {
console.log('Child method called');
}
}
};
</script>





