Vue组件通信的N种姿势,你Pick哪一种?🚀

大家好,我是小杨,一个写了6年前端的老司机。今天聊聊Vue组件通信------这玩意儿就像谈恋爱,得找到合适的沟通方式,不然容易吵架(Bug)!

一、父子组件:Props & Events(最基础,但够用)

场景:爸爸(父组件)要给儿子(子组件)零花钱,儿子要告诉爸爸考试考了多少分。

javascript 复制代码
// 父组件:给钱(传递数据)
<ChildComponent :money="100" @score-change="handleScoreChange" />

methods: {
  handleScoreChange(score) {
    console.log('我儿子考了:', score)
  }
}

// 子组件:收钱 + 汇报成绩
props: ['money'],
methods: {
  reportScore() {
    this.$emit('score-change', 90) // 触发事件
  }
}

适用 :简单直接的上下级关系,但隔代组件用这个会累死(Prop逐层传递警告!)。


二、爷孙组件: <math xmlns="http://www.w3.org/1998/Math/MathML"> a t t r s / attrs / </math>attrs/listeners(隔代传值神器)

场景:爷爷想跳过爸爸直接给孙子塞红包(禁止套娃!)。

javascript 复制代码
// 爷爷组件
<ParentComponent :money="200" :message="'好好学习'" />

// 爸爸组件(中间人,不处理props)
<ChildComponent v-bind="$attrs" />  

// 孙子组件
created() {
  console.log(this.$attrs) // { money: 200, message: "好好学习" }
}

优点 :不用在中间组件一层层声明props,适合高阶组件封装


三、全局事件总线(EventBus):任意组件撩骚

场景:两个毫无关系的组件突然要交换数据(比如A组件点了按钮,B组件要响应)。

javascript 复制代码
// 创建EventBus(通常单独一个文件)
export const eventBus = new Vue()

// A组件发送事件
eventBus.$emit('表白', { name: '我', words: '今晚吃鸡吗?' })

// B组件接收
eventBus.$on('表白', data => {
  console.log(data.words) // 输出:今晚吃鸡吗?
})

注意 :记得在beforeDestroy里用eventBus.$off()取消监听,否则可能内存泄漏


四、Vuex:中央情报局(适合复杂应用)

场景:多个组件要共享用户登录状态、购物车数据等。

javascript 复制代码
// store.js
state: { userName: '我' },
mutations: {
  updateName(state, newName) {
    state.userName = newName // 同步修改
  }
}

// 任意组件修改
this.$store.commit('updateName', '新名字')

// 任意组件读取
computed: {
  userName() {
    return this.$store.state.userName
  }
}

什么时候用?

  • 中大型项目
  • 频繁跨组件共享数据
  • 需要持久化的状态(比如用户Token)

五、Provide / Inject:土豪长辈的遗产继承

场景 :祖传的VIP会员身份,后代组件直接继承,不用层层传递。

javascript 复制代码
// 祖先组件
provide() {
  return { vipLevel: '钻石会员' }
}

// 后代组件(任意层级)
inject: ['vipLevel'],
created() {
  console.log(this.vipLevel) // 钻石会员
}

慎用 :这相当于全局变量,容易导致数据来源不清晰,适合主题配置、国际化等场景。


六、$refs:直接操作组件(简单粗暴)

场景:父组件要直接调用子组件的方法(比如让视频播放器暂停)。

javascript 复制代码
<VideoPlayer ref="videoPlayer" />

methods: {
  handlePause() {
    this.$refs.videoPlayer.pause() // 直接调用子组件方法
  }
}

缺点:破坏了组件封装性,相当于:"儿子,老子命令你立刻写作业!"


七、终极对比表

方式 适用场景 优点 缺点
Props / Events 父子组件简单通信 直观、官方推荐 跨层级麻烦
EventBus 任意组件通信 灵活、解耦 需手动管理监听
Vuex 中大型项目状态管理 集中管理、响应式 略重
Provide / Inject 跨层级共享配置 避免逐层传递 数据来源不透明

八、我的踩坑实录

  1. EventBus忘记销毁:曾经有个页面反复创建/销毁,导致事件重复监听,结果点一次按钮触发N次回调...
  2. Vuex滥用:把本应是组件自身状态的数据塞到Vuex里,导致维护时想打自己。

黄金法则:根据场景选择最简单的方案,别为了用而用!

⭐ 写在最后

请大家不吝赐教,在下方评论或者私信我,十分感谢🙏🙏🙏.

✅ 认为我某个部分的设计过于繁琐,有更加简单或者更高逼格的封装方式

✅ 认为我部分代码过于老旧,可以提供新的API或最新语法

✅ 对于文章中部分内容不理解

✅ 解答我文章中一些疑问

✅ 认为某些交互,功能需要优化,发现BUG

✅ 想要添加新功能,对于整体的设计,外观有更好的建议

✅ 一起探讨技术加qq交流群:906392632

最后感谢各位的耐心观看,既然都到这了,点个 👍赞再走吧!

相关推荐
再学一点就睡2 小时前
手写 Promise 静态方法:从原理到实现
前端·javascript·面试
再学一点就睡2 小时前
前端必会:Promise 全解析,从原理到实战
前端·javascript·面试
OEC小胖胖4 小时前
性能优化(一):时间分片(Time Slicing):让你的应用在高负载下“永不卡顿”的秘密
前端·javascript·性能优化·web
小小李程序员5 小时前
JSON.parse解析大整数踩坑
开发语言·javascript·json
宋辰月5 小时前
Vue2-VueRouter
开发语言·前端·javascript
haaaaaaarry6 小时前
Element Plus常见基础组件(一)
java·前端·javascript·vue.js
萌萌哒草头将军6 小时前
Prisma ORM 又双叒叕发布新版本了!🚀🚀🚀
前端·javascript·node.js
我是ed.7 小时前
cocos Js 使用 webview 通过 postMessage 进行通信
开发语言·javascript·ecmascript
脑袋大大的8 小时前
uni-app x开发避坑指南:拯救被卡顿的UI线程!
开发语言·前端·javascript·vue.js·ui·uni-app·uts
前端Hardy9 小时前
10 分钟搞定婚礼小程序?我用 DeepSeek 把同学的作业卷成了范本!
前端·javascript·微信小程序