大家好,我是小杨,一个写了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 | 跨层级共享配置 | 避免逐层传递 | 数据来源不透明 |
八、我的踩坑实录
- EventBus忘记销毁:曾经有个页面反复创建/销毁,导致事件重复监听,结果点一次按钮触发N次回调...
- Vuex滥用:把本应是组件自身状态的数据塞到Vuex里,导致维护时想打自己。
黄金法则:根据场景选择最简单的方案,别为了用而用!
⭐ 写在最后
请大家不吝赐教,在下方评论或者私信我,十分感谢🙏🙏🙏.
✅ 认为我某个部分的设计过于繁琐,有更加简单或者更高逼格的封装方式
✅ 认为我部分代码过于老旧,可以提供新的API或最新语法
✅ 对于文章中部分内容不理解
✅ 解答我文章中一些疑问
✅ 认为某些交互,功能需要优化,发现BUG
✅ 想要添加新功能,对于整体的设计,外观有更好的建议
✅ 一起探讨技术加qq交流群:906392632
最后感谢各位的耐心观看,既然都到这了,点个 👍赞再走吧!