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是最佳选择。

相关推荐
林十一npc1 分钟前
MySQL索引与视图综合应用示例解析
android·前端·mysql
SuperherRo8 分钟前
Web开发-JavaEE应用&ORM框架&SQL预编译&JDBC&MyBatis&Hibernate&Maven
前端·sql·java-ee·maven·mybatis·jdbc·hibernate
这里有鱼汤9 分钟前
Python 图像处理必备的 15 个基本技能 🎨
前端·后端·python
这里有鱼汤9 分钟前
想学会Python自动化办公?这20个Excel表格操作脚本一定要掌握!
前端·后端·python
爱摄影的程序猿22 分钟前
Python Web 框架 django-vue3-admin快速入门 django后台管理
前端·python·django
大叔_爱编程33 分钟前
wx203基于ssm+vue+uniapp的教学辅助小程序
vue.js·小程序·uni-app·毕业设计·ssm·源码·课程设计
洁洁!36 分钟前
数据采集助力AI大模型训练
前端·人工智能·easyui
MaCa .BaKa42 分钟前
25-智慧旅游系统(协同算法)三端
java·javascript·vue.js·spring boot·tomcat·maven·旅游
MiyueFE1 小时前
bpmn-js 源码篇9:Moddle - 对象格式的标准化定义库
前端·javascript
excel1 小时前
webpack 核心编译器 七 节
前端