主题
组件通信
1. 父子组件通信
1.1 父组件向子组件传递数据
vue
<!-- 父组件 -->
<template>
<child-component
:message="message"
:user="user"
v-bind="$attrs"
></child-component>
</template>
<script>
export default {
data() {
return {
message: 'Hello',
user: { name: 'John' }
}
}
}
</script>
<!-- 子组件 -->
<script>
export default {
props: {
message: String,
user: {
type: Object,
required: true
}
}
}
</script>
1.2 子组件向父组件传递数据
vue
<!-- 子组件 -->
<template>
<button @click="handleClick">发送数据</button>
</template>
<script>
export default {
methods: {
handleClick() {
this.$emit('update', { data: 'some data' })
}
}
}
</script>
<!-- 父组件 -->
<template>
<child-component @update="handleUpdate"></child-component>
</template>
<script>
export default {
methods: {
handleUpdate(data) {
console.log('从子组件接收到数据:', data)
}
}
}
</script>
1.3 兄弟组件通信
1.3.1 通过父组件中转
vue
<!-- 父组件 -->
<template>
<div>
<component-a @message="handleMessage"></component-a>
<component-b :message="message"></component-b>
</div>
</template>
<script>
export default {
data() {
return {
message: ''
}
},
methods: {
handleMessage(msg) {
this.message = msg
}
}
}
</script>
1.3.2 事件总线(EventBus)
js
// eventBus.js
import Vue from 'vue'
export const eventBus = new Vue()
// 组件A
methods: {
sendMessage() {
eventBus.$emit('custom-event', data)
}
}
// 组件B
created() {
eventBus.$on('custom-event', data => {
console.log(data)
})
}
2. 跨层级组件通信
2.1 Provide/Inject
js
// 祖先组件
export default {
provide() {
return {
theme: 'dark',
user: this.user
}
},
data() {
return {
user: { name: 'John' }
}
}
}
// 后代组件
export default {
inject: ['theme', 'user']
}
2.2 Vuex状态管理
js
// store.js
import Vuex from 'vuex'
export default new Vuex.Store({
state: {
count: 0
},
mutations: {
increment(state) {
state.count++
}
}
})
// 组件中使用
export default {
computed: {
count() {
return this.$store.state.count
}
},
methods: {
increment() {
this.$store.commit('increment')
}
}
}
3. Vue3的组件通信
3.1 组合式API通信
js
// 父组件
import { ref, provide } from 'vue'
export default {
setup() {
const message = ref('Hello')
provide('message', message)
return { message }
}
}
// 子组件
import { inject } from 'vue'
export default {
setup() {
const message = inject('message')
return { message }
}
}
3.2 Props和Emits声明
js
// Vue3组件
export default {
props: {
message: String
},
emits: ['update'],
setup(props, { emit }) {
const handleClick = () => {
emit('update', 'new value')
}
return { handleClick }
}
}
4. 进阶通信方式
4.1 $refs引用
vue
<template>
<child-component ref="childRef"></child-component>
</template>
<script>
export default {
mounted() {
// 访问子组件实例
this.$refs.childRef.someMethod()
}
}
</script>
4.2 $parent和$root
js
// 子组件中访问父组件
methods: {
accessParent() {
console.log(this.$parent.parentData)
}
}
4.3 插槽通信
vue
<!-- 父组件 -->
<template>
<child-component>
<template v-slot:default="slotProps">
{{ slotProps.text }}
</template>
</child-component>
</template>
<!-- 子组件 -->
<template>
<div>
<slot :text="message"></slot>
</div>
</template>
5. 最佳实践
5.1 通信方式选择原则
- 父子组件:优先使用props/emit
- 兄弟组件:考虑事件总线或状态管理
- 跨层级组件:使用provide/inject或状态管理
- 全局状态:使用Vuex/Pinia
5.2 性能优化
- 避免过度使用事件总线
- 合理使用计算属性缓存
- 及时销毁事件监听
- 避免深层组件嵌套
5.3 调试技巧
- Vue Devtools监控数据流
- 使用事件追踪
- 控制台调试
- 性能分析