Vue组件通信的N种姿势,你Pick哪一种?[特殊字符]

目录

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

二、爷孙组件:$attrs / $listeners(隔代传值神器)

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

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

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

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

七、终极对比表

八、我的踩坑实录

⭐  写在最后


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

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

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

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

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

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

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


二、爷孙组件:$attrs / $listeners(隔代传值神器)

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

// 爷爷组件
<ParentComponent :money="200" :message="'好好学习'" />

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

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

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


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

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

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

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

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

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


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

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

// 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会员身份,后代组件直接继承,不用层层传递。

// 祖先组件
provide() {
  return { vipLevel: '钻石会员' }
}

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

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


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

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

<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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

江城开朗的豌豆

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值