新闻详情

新闻详情

首页 / 资讯中心 / 详情

Vue 全局事件总线详解

发布时间:2026/11/14 11:57:51来源:尧图网络
Vue 全局事件总线详解
一、什么是事件总线1.1 定义事件总线(Event Bus)本质上就是一个居中转发消息的邮局:发送方不直接找接收方,而是把消息丢给总线,总线再帮转给所有订阅了这个消息的人。在 Vue 里,它用来解决任意两个组件之间通信的问题,不限于父子,不限于兄弟,只要挂在同一条总线上就能互相收发。1.2 生活类比把事件总线想象成广播电台:你想听某个节目 → 先去电台登记订阅(订阅事件)主持人想播报 → 把内容交给电台($emit)电台把内容推给所有登记过的人主持人和听众互相不认识,也不需要知道对方在哪,只跟电台打交道。这就是事件总线的核心思想:解耦发送方和接收方。1.3 为什么要用Vue 组件通信的原生方式有局限:通信方式限制props / emits只能父子,跨层级要一层层透传(Prop Drilling)$refs父直接操作子,反向不行,兄弟也不行provide/inject父给后代单向,后代回父不直接Vuex / Pinia适合管全局状态,小事件通知有点重事件总线就填了这些空缺:任意两个组件都能对话,写法还特别轻。适合做开关侧边栏、“切换主题”、用户登出广播这种一次性通知类需求。二、Vue 2 的实现:用 Vue 实例当总线2.1 核心思路Vue 2 里,每个 Vue 实例都自带事件接口$on/$emit/$off/$once。所以新建一个空的 Vue 实例当总线就行,谁需要谁引入。// src/eventBus.jsimportVuefromvue;constbusnewVue();// ← 一个空实例,啥都没有,但有事件接口exportdefaultbus;2.2 基本用法:订阅 发布// 组件A:订阅login事件importbusfrom/eventBus;exportdefault{created(){bus.$on(login,(user){console.log(收到登录:,user);// ← 任何组件 emit 都能收到});},beforeDestroy(){bus.$off(login);// ← 必须解绑,否则内存泄漏}}// 组件B:发布login事件importbusfrom/eventBus;exportdefault{methods:{doLogin(){bus.$emit(login,{name:张三});// ← 不用管谁在听}}}A 和 B 可能隔着十层组件,可能根本不是父子,但只要都引入了bus,消息就能传过去。2.3 四个 API 速查方法作用用法$on(event, fn)订阅事件bus.$on(hi, fn)$emit(event, …args)发布事件,可带参数bus.$emit(hi, 1, 2)$off(event, fn)解绑;不传 fn 解绑该事件全部bus.$off(hi)或bus.$off(hi, fn)$once(event, fn)订阅一次,触发后自动解绑bus.$once(init, fn)三、Vue 3 的实现:mitt 或手写3.1 为什么 Vue 2 的写法不行了Vue 3移除了实例上的$on/$off/$once(因为想跟组件实例解耦,推荐用 props/emits 显式通信)。所以new Vue()当总线这条路彻底断了,需要换工具。3.2 方案一:用 mitt(推荐)mitt是一个超轻量的事件总线库,~200 字节,API 和 Vue 2 的几乎一样。npminstallmitt// src/eventBus.jsimportmittfrommitt;constbusmitt();// ← 创建总线exportdefaultbus;// 组件A:订阅importbusfrom/eventBus;import{onMounted,onBeforeUnmount}fromvue;exportdefault{setup(){constonLogin(user)console.log(登录:,user);onMounted(()bus.on(login,onLogin));onBeforeUnmount(()bus.off(login,onLogin));return{};}}// 组件B:发布importbusfrom/eventBus;exportdefault{setup(){constdoLogin()bus.emit(login,{name:张三});return{doLogin};}}mitt 的 API 对照:mitt 方法Vue 2 对应备注on(type, handler)$on完全对应emit(type, data)$emit只能传一个 data,不能像 $emit 多参off(type, handler)$off同样支持只传 type 解绑全部clear()无清空所有订阅3.3 方案二:手写一个 EventEmitter不想引入依赖,自己写也很短:// src/eventBus.jsclassEventBus{constructor(){this.mapnewMap();// ← { type: [fn1, fn2, ...] }}on(type,fn){if(!this.map.has(type))this.map.set(type,[]);this.map.get(type).push(fn);}emit(type,...args){constfnsthis.map.get(type);if(!fns)return;fns.forEach(fnfn(...args));}off(type,fn){if(!fn){this.map.delete(type);return;}// ← 不传 fn,清空整个事件constfnsthis.map.get(type);if(fns)this.map.set(type,fns.filter(ff!fn));}clear(){this.map.clear();}}exportdefaultnewEventBus();用法和 mitt 一模一样。手写版的好处是能看清原理,坏处是要自己保证this指向、处理 once 等边缘情况。3.4 注解1.mitt 的 emit 只能带一个参数Vue 2 里可以bus.$emit(hi, 1, 2, 3),mitt 只能bus.emit(hi, { a:1, b:2 }),多个参数要打包成对象。这是设计差异,不是 bug。2.为什么 Vue 3 推荐显式通信却还保留 mitt显式通信(props/emits/provide)在父子链路上更清晰,但跨层级、跨业务模块时,层层透传成本太高。mitt 是为了这类广播型场景留的口子,不是替代 props。四、实战案例:全局侧边栏开关需求:一个按钮(在任何位置)点击后,打开/关闭侧边栏(也在任何位置)。4.1 总线文件// src/eventBus.jsimportmittfrommitt;exportdefaultmitt();4.2 侧边栏组件:监听开关!-- SideBar.vue -- template aside v-showvisible侧边栏内容/aside /template script setup import bus from /eventBus; import { ref, onMounted, onBeforeUnmount } from vue; const visible ref(false); const toggle (v) (visible.value v); // ← 收到指令就改 onMounted(() bus.on(sidebar:toggle, toggle)); onBeforeUnmount(() bus.off(sidebar:toggle, toggle)); /script4.3 触发按钮:发广播!-- MenuButton.vue -- template button clickopen打开侧边栏/button /template script setup import bus from /eventBus; const open () bus.emit(sidebar:toggle, true); // ← 不关心谁在听 /script按钮和侧边栏没有任何 props 约定,谁也不依赖谁。换一个按钮、加一个开关,只要emit(sidebar:toggle, x)就行。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

【外设】之大彩串口显示屏 2026/11/14 3:51:47

【外设】之大彩串口显示屏

大彩串口屏初步使用 1 .官网下载 STM32 屏幕 GUI 设计资料 http://www.gz-dc.com/category/typeid/4112 找到 STM32 Keil 工程,移植相关代码因项目而异进行移植,由于项目简单,本人只对用到的指令接口进行修改。 比如:注意事项&…

阅读更多 →
无法下载Windows系统iso文件 2026/11/12 23:59:09

无法下载Windows系统iso文件

当我遇到这个问题的时候,我打开了一个网站: 登录 然后我打算下载的时候: 突然那个官方的连接就可以下载了:

阅读更多 →
【清华代码熊】DeepSeek V4.1 Flash 后训练详解 2026/11/14 10:11:15

【清华代码熊】DeepSeek V4.1 Flash 后训练详解

📌 上期解析了 DeepSeek V4.1 Flash 模型架构改进,本期解析 DeepSeek V4.1 Flash 预训练/后训练技术: 🌟 预训练:45T 文本 多模态混合语料、直接训练 sparse attention(取消 DeepSeek V4 的 dense 冷启动&…

阅读更多 →
Shuffle-R1: Efficient RL framework for Multimodal Large Language Models via Data-centric Dynamic ... 2026/11/13 13:31:48

Shuffle-R1: Efficient RL framework for Multimodal Large Language Models via Data-centric Dynamic ...

文章主要内容和创新点 主要内容 本文聚焦于多模态大语言模型(MLLM)强化学习(RL)训练中的效率问题,提出了一个名为Shuffle-R1的框架。研究发现,当前RL训练存在两个关键缺陷: 优势值坍缩(Advantage Collapsing):批次中大多数优势值集中在零附近,导致有效梯度信号被淹…

阅读更多 →
PRvL: Quantifying the Capabilities and Risks of Large Language Models for PII Redaction 2026/11/13 16:11:45

PRvL: Quantifying the Capabilities and Risks of Large Language Models for PII Redaction

一、文章主要内容总结 本文聚焦于利用大型语言模型(LLMs)实现个人身份信息(PII)脱敏的研究,旨在解决传统脱敏方法(如基于规则的系统、领域特定命名实体识别(NER)模型)泛化能力差、跨格式/跨语境适应性弱的问题。 研究通过全面评估多种LLM架构(包括密集型LLM(D-LLM…

阅读更多 →
LLaVA-RE: Binary Image-Text Relevancy Evaluation with Multimodal Large Language Model 2026/11/14 3:51:43

LLaVA-RE: Binary Image-Text Relevancy Evaluation with Multimodal Large Language Model

文章主要内容和创新点 主要内容 本文聚焦于二进制图像-文本相关性评估任务(判断图像与文本“相关”或“不相关”),针对该任务中文本格式多样、相关性定义随场景变化等挑战,提出了基于多模态大语言模型(MLLM)的解决方案LLaVA-RE。 模型设计:LLaVA-RE基于LLaVA 1.5架构,…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉