当前位置: 首页 > 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.xdnf.cn/news/1163197.html

相关文章:

  • ps aux 和 ps -ef
  • react class和function 如何模拟vue中的 双向绑定 监听 computed的方式
  • 区块链之以太坊合约开发工具——Metamask钱包和Remix IDE
  • 架构设计衡量标准
  • 系统分析师-计算机系统-操作系统-存储器管理设备管理
  • 【每日算法】专题四_前缀和
  • 【算法基础】二分查找
  • 选择排序 冒泡排序
  • TPS61194PWPRQ1适用于汽车照明低 EMI、高性能 4 通道 LED 驱动器TPS61194
  • Java 二叉树
  • 【Java学习|黑马笔记|Day19】方法引用、异常(try...catch、自定义异常)及其练习
  • 洛谷 P1480 A/B Problem
  • Apache Ignite Binary Object 调优
  • Js进阶案例合集
  • 《使用Qt Quick从零构建AI螺丝瑕疵检测系统》——1. 启航:你的第一个工业视觉应用
  • 原型设计模式
  • GaussDB alter table的用法
  • 有关Mysql数据库的总结
  • 45.sentinel自定义异常
  • QGIS、ArcMap、ArcGIS Pro中的书签功能、场景裁剪
  • Vue过度与动画效果
  • 如何用 Z.ai 生成PPT,一句话生成整套演示文档
  • 用 STM32 的 SYSTICK 定时器与端口复用重映射玩转嵌入式开发
  • 用Java 代码实现一个简单的负载均衡逻辑
  • redis 如何优雅地进行键设计?
  • 数据结构之克鲁斯卡尔算法
  • 编译支持cuda硬件加速的ffmpeg
  • Vue 3 响应式原理详细解读【一】—— Proxy 如何突破 defineProperty 的局限
  • BEVformer个人理解与解读
  • LLaMA-Factory 微调可配置的模型基本参数