千家信息网

Vue2响应式系统之异步队列怎么实现

发表于:2025-11-14 作者:千家信息网编辑
千家信息网最后更新 2025年11月14日,这篇"Vue2响应式系统之异步队列怎么实现"文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这
千家信息网最后更新 2025年11月14日Vue2响应式系统之异步队列怎么实现

这篇"Vue2响应式系统之异步队列怎么实现"文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇"Vue2响应式系统之异步队列怎么实现"文章吧。

试想一下如果这里的 console.log 是渲染页面,那改变一次值就刷新一下页面,会造成严重的性能问题,页面也会不停的改变。

场景

import { observe } from "./reactive";import Watcher from "./watcher";const data = {    a: 1,    b: 2,    c: 3,};observe(data);const updateComponent = () => {    console.log(data.a + data.b);};new Watcher(updateComponent);const updateComponent2 = () => {    console.log(data.c);};new Watcher(updateComponent2);data.a = 2;data.a = 3;data.b = 4;data.c = 5;

new Watcher(updateComponent) 进行依赖收集会输出一次 3 ,new Watcher(updateComponent2) 进行依赖收集也会输出一次 3 。

之后我们依次改变 a、 a 、b、c 的值,每改变一次就会触发 Watcher 的执行,会连续进行四次的 console.log。

试想一下如果这里的 console.log 是渲染页面,那改变一次值就刷新一下页面,会造成严重的性能问题,页面也会不停的改变。

解决方案

我们可以通过一个队列,收集所有的 Watcher 。

那什么时候执行 Watcher 队列呢?

为了等所有的 Watcher 都收集完毕,可以将 Watcher 的执行放到 setTimeout 中。这样当主线程全部执行后,才会去执行 Watcher 队列。

代码实现

我们可以给每一个 Watcher 加上一个 id,如果队列中已经有 id 了就不加入队列。

let uid = 0;export default class Watcher {    constructor(Fn, options) {        this.getter = Fn;        this.depIds = new Set(); // 拥有 has 函数可以判断是否存在某个 id        this.deps = [];        this.newDeps = []; // 记录新一次的依赖        this.newDepIds = new Set();       /******新增 *************************/        this.id = ++uid; // uid for batching        // options        if (options) {            this.sync = !!options.sync;        }       /************************************/        this.get();    }    ...}

我们同时提供了一个 options 对象,保存了其中的 sync 字段,表示是像之前一样立即出触发 Watcher 还是放到队列中。

然后 Watcher 的 update 方法中我们去调用加入队列的函数。

export default class Watcher {    ...    update() {        if (this.sync) {            this.run(); // 直接运行        } else {            queueWatcher(this); // 加入队列        }    }    ...}

看一下 queueWatcher 的实现。

const queue = []; // 保存 Watcher 队列let has = {}; // 去重 Watcherlet waiting = false; // 是否加入到了 setTimeout 队列export function queueWatcher(watcher) {    const id = watcher.id;    if (has[id] == null) {        has[id] = true;        queue.push(watcher); // 加入队列        // queue the flush        if (!waiting) { // 执行 Watcher 函数放到 setTimeout 队列中,只加入一次即可            waiting = true;            setTimeout(flushSchedulerQueue, 0);        }    }}

再看一下上边执行 Watcher 队列的 flushSchedulerQueue 函数的实现。

let flushing = false; // 是否正在执行队列let index = 0;/** * Flush both queues and run the watchers. */function flushSchedulerQueue() {    flushing = true;    let watcher, id;    for (index = 0; index < queue.length; index++) {        watcher = queue[index];        id = watcher.id;        has[id] = null;        watcher.run();    }    resetSchedulerState(); // 执行结束后进行重置}/** * Reset the scheduler's state. */function resetSchedulerState() {    index = queue.length = 0;    has = {};    waiting = flushing = false;}

总体上就是上边的样子了。

执行结果

import { observe } from "./reactive";import Watcher from "./watcher";const data = {    a: 1,    b: 2,    c: 3,};observe(data);const updateComponent = () => {    console.log(data.a + data.b);};new Watcher(updateComponent);const updateComponent2 = () => {    console.log(data.c);};new Watcher(updateComponent2);data.a = 2;data.a = 3;data.b = 4;data.c = 5;

虽然后边我们改变了四次 data 中的值,但事实上只有两个 Watcher ,因此只会输出两次。

以上就是关于"Vue2响应式系统之异步队列怎么实现"这篇文章的内容,相信大家都有了一定的了解,希望小编分享的内容对大家有帮助,若想了解更多相关的知识内容,请关注行业资讯频道。

队列 页面 内容 函数 系统 输出 上边 就是 性能 文章 知识 篇文章 问题 两个 事实 事实上 代码 价值 只有 可以通过 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 质量追溯软件开发公司 合肥新富财经股票软件开发公司 就业率高的计算机网络技术 网络安全法培训免费ppt 今日关注网络安全 广电总局网络技术研究所 兰州三维互联网科技公司 协助调查证据是大数据库吗 服务器机柜上的电脑 gp数据库数据倾斜处理 服务器和粉丝可以一起用吗 flink 累加器更新数据库 闲置电脑怎么做云服务器 最全小说软件开发 雅虎邮箱接受服务器是什么意思 达梦数据库打印输出语句 爬走网络安全手抄报 怀旧服哪个服务器刷副本快 安防系统软件开发 秦时明月手游服务器 5e无法进入安全服务器 怎么租服务器玩海外游戏 服务器滑轨坏了 小程序域名服务器是否需要备案 为什么网络安全法施行不打击骚扰 高盛软件开发师代替交易员 拿到服务器应该怎么管理 应用安全配置服务器 网络安全包括哪两个方面的内容 服务器机箱电源设置
0