当前位置: 首页 > news >正文

Vue组件之间通信

一、组件自定义事件:子传父通信方案

1. 基本使用方式

1.1 直接绑定方式(推荐)
<!-- 父组件 Parent.vue -->
<template><Child @custom-event="handleEvent" />
</template><script>
import Child from './Child.vue'export default {components: { Child },methods: {handleEvent(payload) {console.log('收到子组件数据:', payload)}}
}
</script><!-- 子组件 Child.vue -->
<template><button @click="sendData">传递数据</button>
</template><script>
export default {methods: {sendData() {this.$emit('custom-event', {data: '子组件数据'})}}
}
</script>
1.2 通过ref绑定方式
<!-- 父组件 Parent.vue -->
<template><Child ref="childRef" />
</template><script>
import Child from './Child.vue'export default {components: { Child },mounted() {this.$refs.childRef.$on('custom-event', this.handleEvent)},beforeDestroy() {this.$refs.childRef.$off('custom-event')},methods: {handleEvent(payload) {console.log('收到子组件数据:', payload)}}
}
</script>

2. 关键特性解析

  1. 一次性事件:使用once修饰符或$once方法

  2. <Child @custom-event.once="handleEvent" />
    <!-- 或 -->
    mounted() {this.$refs.childRef.$once('custom-event', this.handleEvent)
    }
  3. 事件解绑

// 解绑单个事件
this.$off('custom-event')
// 解绑多个事件
this.$off(['event1', 'event2'])
// 解绑所有事件
this.$off()

3. 原生事件绑定

<Child @click.native="handleClick" />

this指向问题

* 使用methods方法或箭头函数:this指向父组件实例

* 使用普通函数:this指向子组件实例

二、全局事件总线:任意组件通信方案

1. 初始化配置

// main.js
new Vue({beforeCreate() {Vue.prototype.$bus = this // 安装全局事件总线},render: h => h(App)
}).$mount('#app')

2. 实际应用案例

// 组件A(接收数据)
export default {mounted() {this.$bus.$on('data-event', this.handleData)},beforeDestroy() {this.$bus.$off('data-event')},methods: {handleData(payload) {console.log('接收数据:', payload)}}
}// 组件B(发送数据)
export default {methods: {sendData() {this.$bus.$emit('data-event', {message: '跨组件数据'})}}
}

3. 使用建议

  1. 事件命名:使用命名空间避免冲突(如user:updated

  2. 及时解绑:在beforeDestroy钩子中解绑事件

  3. 适度使用:复杂场景考虑Vuex/Pinia状态管理

三、消息订阅与发布:第三方解决方案

1. 基本使用流程

// 安装
npm install pubsub-js
// 组件A(订阅消息)
import pubsub from 'pubsub-js'export default {mounted() {this.pubId = pubsub.subscribe('data-channel', (msgName, data) => {console.log('收到消息:', data)})},beforeDestroy() {pubsub.unsubscribe(this.pubId)}
}// 组件B(发布消息)
import pubsub from 'pubsub-js'export default {methods: {publishData() {pubsub.publish('data-channel', {info: '跨组件消息'})}}
}

2. 与全局事件总线对比

特性全局事件总线消息订阅发布
实现方式Vue原生实现第三方库实现
体积无额外体积需要引入pubsub-js
调试支持可通过Vue开发者工具查看需要额外调试工具
类型支持有限更好
取消订阅需要手动维护提供订阅ID管理
适合场景简单项目复杂或大型项目

四、nextTick:DOM更新后的回调机制

1. 核心用法示例

<template><div ref="content">{{ message }}</div><button @click="updateMessage">更新</button>
</template><script>
export default {data() {return {message: '初始消息'}},methods: {updateMessage() {this.message = '更新后的消息'// 此时DOM尚未更新console.log(this.$refs.content.textContent) // '初始消息'this.$nextTick(() => {// DOM已更新console.log(this.$refs.content.textContent) // '更新后的消息'})}}
}
</script>

 

2. 典型应用场景

  1. 操作更新后的DOM

this.someData = newValue
this.$nextTick(() => {this.$refs.element.doSomething()
})

2. 等待视图更新后执行计算

this.items.push(newItem)
this.$nextTick(() => {this.calculateLayout()
})

3. 与第三方库集成

this.showModal = true
this.$nextTick(() => {$(this.$refs.modal).modal('show')
})

3. 实现原理说明

Vue的DOM更新是异步执行的,数据变化后:

  1. Vue开启一个队列缓冲同一事件循环中的数据变更

  2. 下一个事件循环"tick"中刷新队列并执行实际工作

  3. nextTick将回调延迟到下次DOM更新循环之后执行

五、技术使用建议

通信场景推荐方案理由
父子组件通信自定义事件/propsVue原生支持,简单直接
兄弟组件通信全局事件总线/状态管理避免复杂的组件层级传递
跨多级组件通信状态管理/Provide/Inject避免逐层传递的繁琐
非父子关系组件通信(简单场景)全局事件总线轻量级解决方案
非父子关系组件通信(复杂场景)状态管理集中式状态管理更易维护
需要等待DOM更新的操作nextTick确保在正确时机操作DOM
需要与第三方库集成的发布订阅需求pubsub-js功能更强大,支持更复杂的消息传递场景

六、常见问题解决方案

  1. 自定义事件不触发

    • 检查事件名称是否完全匹配(大小写敏感)

    • 确认$emit在子组件正确执行

    • 检查父组件监听的事件名称是否正确

  2. 内存泄漏

    • 确保在beforeDestroy中解绑所有事件

    • 使用$once处理只需触发一次的事件

  3. nextTick回调不执行

    • 确认数据确实发生了变化

    • 检查是否在正确的上下文中调用(组件实例内)

  4. pubsub-js消息混乱

    • 使用更具体的事件名称

    • 考虑添加命名空间前缀

    • 确保及时取消订阅

 

http://www.dtcms.com/a/290440.html

相关文章:

  • 使用相机不同曝光时间测试灯光闪烁频率及Ai解释
  • 【Java + Vue 实现图片上传后 导出图片及Excel 并压缩为zip压缩包】
  • 过往记录系列 篇七:大A突破3500点历史梳理
  • STM32 USB键盘实现指南
  • 格式工厂5.21.0简介
  • Idea上拉取代码解决冲突的总结
  • Scott Brinker:Martech代理时代兴起,结构性的洗牌刚刚开始;SaaS定价模式迅速被按效果付费所取代
  • 时序数据库在工业物联网领域的核心优势与应用价值
  • mongodb源代码分析createCollection命令由create.idl变成create_gen.cpp过程
  • MongoDB 查询时区问题
  • MySQL主从同步集群(Docker搭建)
  • 安装docker可视化工具 Portainer中文版(ubuntu上演示,所有docker通用) 支持控制各种容器,容器操作简单化 降低容器门槛
  • 详解 F.cross_entropy 与标签平滑的工作原理
  • MySQL(05) mysql锁,MVCC、Innodb行锁
  • 【初识Qt】
  • node.js 为什么要装 express组件
  • 如何使用电脑连接小米耳机(红米 redmi耳机)
  • HTTP,HTTPS
  • uniapp【uni-ui】【vue3】样式覆盖方式记录
  • uniapp vue3 vite项目使用微信云开发(云函数)
  • 全新开发范式:uni-app X助力全平台原生应用
  • uni-app 鸿蒙平台条件编译指南
  • 基于FPGA的IIC控制AHT20读取温湿度
  • 查看两个tv and 手机模拟器的ip
  • 探索无广告音乐世界:MusicFree 免费播放器
  • 【LuckiBit】macOS/Linux 常用命令大全
  • Java面试题034:一文深入了解MySQL(6)
  • rancher上使用rke在华为云多网卡的服务器上安装k8s集群问题处理了
  • C#最佳实践:为何应尽量减少静态类的使用
  • 华为云Stack交付流程