游乐游手机版
首页/前端开发/文章详情

手把手带你实现Vue源码中的发布订阅模式

时间:2026-07-18 06:43
发布订阅模式通过调度中心中转信息,实现发布者与订阅者解耦。Vue响应式系统结合数据劫持与发布订阅,核心角色包括订阅者、调度中心和发布者。代码示例展示了典型实现:订阅者注册事件到调度中心,发布者触发事件时执行对应回调。

今天聊聊发布订阅模式。这玩意儿其实挺生活化的——你微信上关注了一堆公众号,哪天这些号更新了,微信就会弹个通知告诉你。说白了,这就是发布订阅的一种简单写照。

关键点在于:发布者和订阅者之间并不直接打交道,而是通过一个调度中心来中转信息。一个事件可以被多个订阅者监听,一个订阅者也能同时关心多个不同的事件

手把手带你实现发布订阅模式--Vue源码

Vue的响应式系统,本质上就是数据劫持跟发布订阅模式结合后的产物。想真正理解Vue的设计思路,绕不开对这个模式的理解。

整个模式里,有三个核心角色:

  • 订阅者:把自己想监听的事件,提前登记到调度中心里。
  • 调度中心:当发布者通知有任务时,由它负责唤起所有相关的订阅者(也就是执行他们留下的代码)。
  • 发布者:把任务或事件,推送到调度中心。

理论说太多容易晕,直接看代码实现。

 复制代码html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Documenttitle>
head>
<body>
    <script>
        class Publish {
            constructor() {
                // 调度中心,订阅者把自己要订阅的东西注册到这里
                // this.events = {
                //      event1: [fn1, fn2, fn3]
                //      event2: [fn1, fn2]
                //}
                this.events = {}
            }            // 订阅,订阅者把把事件注册到调度中心
            $on(type, fn) {
                if (!this.events[type]) {
                    this.events[type] = []
                }                this.events[type].push(fn)
            }            // 发布,通过调度中心发布
            $emit(type) {
                if (this.events[type]) {
                    const args = Array.prototype.slice.call(arguments, 1)
                    this.events[type].forEach(fn => {
                        fn(...args)
                    });
                }
            }
        }        const eventHub = new Publish()        // 订阅:把事件注册到调度中心
        eventHub.$on('sum', function() {
            const total = [...arguments].reduce((x, y) => x + y)
            console.log(total)
        })        // 发布:如果有人订阅,那么就执行注册的代码
        eventHub.$emit('sum', 1, 2, 3)
    script>
body>
html>

发布订阅的实现方式有很多种,上面这段代码展示的,是Vue里比较典型的一种思路。

接下来,再看看观察者模式。

来源:https://juejin.cn/post/7660707431753891846
上一篇Vite多入口Vue组件库首屏优化:从17MB到按需加载 下一篇Vue2 portal-target组件与Vue3优化方案对比
本站内容用于信息整理与展示,如有侵权或内容问题请及时联系处理。

相关推荐

补充同频道和同主题内容,方便继续浏览更多相关内容。

同类最新

继续查看同栏目最近更新的文章。

更多
JavaScript有效防止原型污染影响属性存在性检查
前端开发 · 2026-07-18

JavaScript有效防止原型污染影响属性存在性检查

防止原型污染,进行属性存在性检查应使用`Object hasOwn()`绕过原型链上的属性,兼容旧环境时则使用`Object prototype hasOwnProperty call()`。避免使用`in`操作符或直接值判断。治本之策是移除`__proto__`等危险键,用`Object create(null)`创建无原型链的对象,并冻结`Object

如何利用Promise简化前端状态管理的高效实用方法
前端开发 · 2026-07-18

如何利用Promise简化前端状态管理的高效实用方法

Promise的三种状态与链式调用天然适合组织异步流程,结合Promise withResolvers可解耦创建与决议。在UI框架中,Promise实例可直接驱动声明式状态渲染,减少手动维护变量,让状态管理回归本质,并提升代码可读性与可维护性,实现直观的异步状态驱动。

JavaScript内存泄露常见代码模式识别方法
前端开发 · 2026-07-18

JavaScript内存泄露常见代码模式识别方法

JavaScript内存泄漏源于对象不可达却被强引用,典型模式包括意外全局变量、未清理的定时器、DOM引用残留、闭包长期持有大对象及模块静态引用累积。需借助DevTools堆快照定位持续增长的对象与保留者。

JavaScript展开运算符与深拷贝的不可变数据实现对比
前端开发 · 2026-07-18

JavaScript展开运算符与深拷贝的不可变数据实现对比

展开运算符仅浅拷贝第一层属性,对嵌套对象无效但执行高效;深拷贝递归复制所有层级实现完全隔离,但存在性能开销与循环引用问题。实际开发中推荐组合展开运算符与手动深层覆盖,或借助Immer库,仅在嵌套极深时使用structuredClone。

V8引擎编译优化对JavaScript内存占用的影响
前端开发 · 2026-07-18

V8引擎编译优化对JavaScript内存占用的影响

V8引擎的编译优化通过字节码紧凑表示节省约一半内存,隐藏类共享减少对象结构开销,TurboFan编译器执行常量折叠、死代码消除、内联及类型反馈精简表示,分代垃圾回收采用新生代半空间复制与老生代增量标记,有效控制内存峰值并加速短期对象回收。