Vue组件通信

Vue 组件通信是构建复杂应用的基础,以下是 Vue 2 和 Vue 3 中所有主要的组件通信方式及其适用场景:

一、父子组件通信

1. Props(父 → 子)

vue 复制代码
<!-- 父组件 -->
<ChildComponent :title="pageTitle" :user="userData" />

<!-- 子组件 -->
<script>
export default {
  props: {
    title: String,
    user: {
      type: Object,
      default: () => ({})
    }
  }
}
</script>

特点:单向数据流,适合父向子传值

2. $emit / 自定义事件(子 → 父)

vue

复制

xml 复制代码
<!-- 子组件 -->
<button @click="$emit('update', newValue)">提交</button>

<!-- 父组件 -->
<ChildComponent @update="handleUpdate" />

特点:子组件触发父组件方法

3. v-model(双向绑定)

vue 复制代码
<!-- Vue 3 默认方式 -->
<CustomInput v-model="searchText" />

<!-- 子组件实现 -->
<input :value="modelValue" @input="$emit('update:modelValue', $event.target.value)" />
<script>
export default {
  props: ['modelValue'],
  emits: ['update:modelValue']
}
</script>

二、跨层级组件通信

4. Provide / Inject(依赖注入)

javascript 复制代码
// 祖先组件 (Vue 3)
import { provide } from 'vue'
export default {
  setup() {
    provide('theme', 'dark')
  }
}

// 后代组件
import { inject } from 'vue'
export default {
  setup() {
    const theme = inject('theme', 'light') // 默认值
    return { theme }
  }
}

特点:适合深层嵌套组件通信

5. 事件总线(Event Bus)

javascript 复制代码
// Vue 3 需要外部库(如 mitt)
// bus.js
import mitt from 'mitt'
export default mitt()

// 组件A(发送)
import bus from './bus'
bus.emit('event-name', data)

// 组件B(接收)
bus.on('event-name', data => { ... })

// 记得在组件卸载时移除监听
onUnmounted(() => {
  bus.off('event-name')
})

特点:任意组件间通信,但需注意内存泄漏

三、状态管理方案

6. Vuex(Vue 2 官方状态管理)

javascript 复制代码
// store.js
import { createStore } from 'vuex'

export default createStore({
  state: { count: 0 },
  mutations: {
    increment(state) {
      state.count++
    }
  },
  actions: {
    incrementAsync({ commit }) {
      setTimeout(() => commit('increment'), 1000)
    }
  }
})

// 组件中使用
import { useStore } from 'vuex'
export default {
  setup() {
    const store = useStore()
    return {
      count: computed(() => store.state.count),
      increment: () => store.commit('increment')
    }
  }
}

7. Pinia(Vue 3 推荐状态管理)

javascript 复制代码
// stores/counter.js
import { defineStore } from 'pinia'

export const useCounterStore = defineStore('counter', {
  state: () => ({ count: 0 }),
  actions: {
    increment() {
      this.count++
    }
  }
})

// 组件中使用
import { useCounterStore } from '@/stores/counter'
export default {
  setup() {
    const counter = useCounterStore()
    return { counter }
  }
}

特点:更简单、类型安全、组合式API友好

四、模板引用通信

8. ref / $refs

vue 复制代码
<!-- 父组件 -->
<ChildComponent ref="child" />

<script>
export default {
  mounted() {
    this.$refs.child.methodName() // 调用子组件方法
    this.$refs.child.property = value // 访问子组件属性
  }
}
</script>

特点:直接访问组件实例,但应谨慎使用

五、其他通信方式

9. attrs/attrs/listeners(Vue 2)

vue 复制代码
<!-- 父组件 -->
<ChildComponent v-bind="$attrs" v-on="$listeners" />

<!-- Vue 3 中已合并到 $attrs -->

10. parent/parent/children

javascript 复制代码
// 子组件中
this.$parent.methodName()

// 父组件中
this.$children[0].property = value

特点:不推荐使用,破坏组件封装性

11. 全局状态(不推荐)

javascript 复制代码
// main.js
app.config.globalProperties.$appName = 'My App'

// 组件中
this.$appName

六、通信方式选择指南

通信方式 适用场景 Vue 2 Vue 3 备注
Props 父→子数据传递 ✅ ✅ 推荐首选
$emit 子→父事件通知 ✅ ✅ 推荐首选
v-model 表单双向绑定 ✅ ✅ 语法糖
Provide/Inject 跨层级传递 ✅ ✅ 适合主题/配置
事件总线 任意组件通信 ✅ ⚠️需库 注意内存泄漏
Vuex 复杂状态管理 ✅ ⚠️兼容 Vue 2首选
Pinia 现代状态管理 ❌ ✅ Vue 3首选
$refs 直接访问组件 ✅ ✅ 应急方案
$attrs 属性透传 ✅ ✅ 高阶组件
$parent 访问父实例 ✅ ❌ 不推荐

最佳实践建议

  1. 简单场景:优先使用 props + emit
  2. 兄弟组件:提升状态到共同父级或使用状态管理
  3. 跨层级:使用 Provide/Inject 或状态管理
  4. 全局状态:使用 Pinia/Vuex
  5. 避免:直接修改子组件状态($refs)、过度使用事件总线
  6. TypeScript:为所有通信方式添加类型定义

Vue 3 组合式API通信示例

javascript 复制代码
// useCounter.js - 可组合函数
import { ref } from 'vue'

export function useCounter() {
  const count = ref(0)
  const increment = () => count.value++
  
  return { count, increment }
}

// 组件A
import { useCounter } from './useCounter'
const { count, increment } = useCounter()

// 组件B
import { useCounter } from './useCounter'
const { count } = useCounter() // 共享状态

选择通信方式时应考虑组件关系、数据流清晰度和长期维护成本。对于新项目,Vue 3 + Pinia + 组合式API是最佳选择。

相关推荐
缓慢更新7 分钟前
AI 辅助生成单测:从接口定义到用例的流水线
java·服务器·前端·网络·数据库·人工智能
陈随易37 分钟前
AI 运维服务器,安全又可靠的方法
前端·后端·程序员
风骏时光牛马1 小时前
AI稳定性治理体系构建与疑难问题深度分析
前端
IT_陈寒2 小时前
JavaScript的this坑人实录,这次我真的记下来了
前端·人工智能·后端
开开心心就好3 小时前
音频降噪剪辑工具,音量裁剪一键处理
运维·服务器·前端·spring·ocr·音视频·1024程序员节
PedroQue995 小时前
0.8.2 新增 backFallback 配置,无 tabbar 页返回无忧
前端·uni-app
淡漠的蓝精灵5 小时前
web.py:一个简单到极致的 Python Web 框架
开发语言·前端·python·其他
开开心心就好6 小时前
竖式除法出题工具,整除余数混合模式
运维·服务器·前端·javascript·ocr·perl·1024程序员节
起个名字费劲死了6 小时前
Halcon学习一:骰子识别
前端·python·学习
大江东去浪淘尽千古风流人物6 小时前
【HexVIO】DSP卸载双目惯性VIO:Hexagon向量化前端与单帧融合调度深度解析
前端·状态模式·slam·dsp·vio·hexagon·移动端加速