$nextTick 实现原理

Vue 使用 nextTick 来确保数据更新后的 DOM 操作在更新完成后执行。其核心逻辑是将回调放到微任务或宏任务队列中,确保回调在 DOM 更新完成后执行。

Vue.js 会利用不同的浏览器 API 来模拟 nextTick 的延迟执行,通常是通过:

  1. Promise:在微任务队列中执行。
  2. setTimeout:在宏任务队列中执行(当浏览器不支持 Promise 时)。

Vue.js 的 nextTick 会将回调函数放到合适的队列中执行。通过不同的 异步队列机制 来确保在 DOM 更新后执行回调函数。实现方式如下:

function nextTick(callback) {if (Promise) {Promise.resolve().then(callback);  // 使用 Promise 微任务队列} else if (setImmediate) {setImmediate(callback);  // 支持 setImmediate} else {setTimeout(callback, 0);  // 最终回退到 setTimeout}
}

实现流程:

  1. 回调队列:callbacks 用于存储所有通过 nextTick 添加的回调函数。
  2. 防止重复调用:pending 用于标记当前是否已经在等待刷新回调,避免重复调用。
  3. 任务优先级选择:Promise 微任务 > MutationObserver>setTimeout(宏任务)
  4. 执行回调:flushCallbacks 会执行所有的回调函数,并清空队列。
let callbacks = [];      // 存储回调函数的数组,用于收集 nextTick 的回调
let pending = false;     // 标记当前是否已经在等待刷新回调,防止多次触发function flushCallbacks() {pending = false;       // 重置标记,表示已经进入回调执行阶段// 复制回调数组,防止在执行回调时继续往 callbacks 里添加新的回调const copies = callbacks.slice(0);callbacks.length = 0;  // 清空原始回调数组// 逐个执行回调函数for (let i = 0; i < copies.length; i++) {copies[i]();}
}let timerFunc;// 优先使用 Promise 微任务,其次是 MutationObserver,最后是 setTimeout
if (typeof Promise !== 'undefined') {const p = Promise.resolve();     // 创建一个 resolved 状态的 Promise 实例timerFunc = () => {p.then(flushCallbacks);        // 使用 Promise.then 触发微任务队列中的 flushCallbacks};
} else if (typeof MutationObserver !== 'undefined') {let counter = 1;const observer = new MutationObserver(flushCallbacks);  // 使用 MutationObserver 监听数据变化触发 flushCallbacksconst textNode = document.createTextNode(String(counter)); // 创建文本节点作为观察对象observer.observe(textNode, { characterData: true });    // 监听文本节点的数据变化timerFunc = () => {counter = (counter + 1) % 2;  // 切换 counter 值,触发文本节点变化textNode.data = String(counter); // 触发 MutationObserver 回调};
} else {timerFunc = () => {setTimeout(flushCallbacks, 0); // 最后降级到使用 setTimeout 延迟执行 flushCallbacks};
}function nextTick(cb) {callbacks.push(cb);    // 将回调函数存入 callbacks 数组中if (!pending) {        // 如果没有待处理的回调任务pending = true;      // 设置标记,防止重复触发timerFunc();         // 调用 timerFunc,触发回调执行机制}
}
  • callbacks 存储所有传入的回调函数。

  • pending 标记防止 timerFunc 多次调用,确保只在本次任务队列完成后触发。

  • flushCallbacks 函数会在 timerFunc 被触发时执行,清空原数组 callbacks 并执行所有回调函数。

  • timerFunc 的优先级选择:

    • Promise:优先使用 Promise 的 then 方法,将 flushCallbacks 放入微任务队列,微任务优先于宏任务。
    • MutationObserver:在不支持 Promise 时,使用 MutationObserver 来监听文本节点变化。每次 timerFunc 被调用,都会修改文本节点内容,触发 MutationObserver 回调。
    • setTimeout:如果以上两种都不支持,使用 setTimeout(宏任务)延迟执行。
  • nextTick 将传入的回调 cb 存入 callbacks 队列,并确保 flushCallbacks 仅被触发一次。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/466037.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C6.【C++ Cont】cout的格式输出

目录 1.头文件 2.使用 1.控制宽度和填充 setw函数(全称set field width设置字段宽度) setfill函数(全称Set fill character设置填充字符) 2.控制数值格式 3.控制整数格式 4.控制对齐方式 1.头文件 用cout进行格式化输出前,先引用头文件iomanip(全称input&output m…

基于SSM+小程序的高校寻物平台管理系统(失物1)

&#x1f449;文末查看项目功能视频演示获取源码sql脚本视频导入教程视频 1、项目介绍 本基于微信小程序的高校寻物平台有管理员&#xff0c;用户以及失主三个角色。 1、管理员功能有个人中心&#xff0c;用户管理&#xff0c;失主管理&#xff0c;寻物启示管理&#xff0c;拾…

视频——教学篇——拍摄和剪辑

文章目录 拍摄与录制。如何提升音质&#xff1f;如何提升画质&#xff1f;一、提升视频呈现的重点1.音质在很大程度上优先于画质2.在音质层面&#xff0c;环境可能比设备好坏更重要。3.提升视频画面方面&#xff0c;打光比买更好的相机更重要。4.画面的构图不如分镜的节奏来的重…

在线绘制带颜色标注的大脑脑区图

导读&#xff1a;大脑是人体最为复杂的器官之一&#xff0c;由多个功能特化的脑区构成。每个脑区承担着特定的生理和认知功能。通过应用定量数据映射技术&#xff0c;将数值以色彩编码的形式呈现于各个脑区&#xff0c;可以显著增强对不同脑区定量信息的视觉识别和理解。 《bio…

第十九周机器学习笔记:GAN的数学理论知识与实际应用的操作

第十九周周报 摘要Abstratc一、机器学习——GAN Basic Theory1. Maximum Likelihood Estimation2. 复习训练GAN的过程3. Objective function与JS散度相关性推导4. GAN的实际做法 总结 摘要 本周周报主要围绕生成对抗网络&#xff08;GAN&#xff09;的基础知识和理论进行深入探…

刷题小记11:栈队列

包括单调栈和优先队列 232. 用栈实现队列 用栈实现队列 两个栈 入队&#xff1a;向入队栈中加入元素 出队&#xff1a;从出队栈中出栈元素&#xff0c;如果出队栈为空&#xff0c;将入队栈所有元素入栈到出队栈。这样顺序就对了 225. 用队列实现栈 用队列实现栈 优化 …

【Qt问题】解决 Cannot retrieve debugging output

【Qt问题】解决 Cannot retrieve debugging output Chapter1 【Qt问题】解决 Cannot retrieve debugging output方案1 关闭其他Qt工程实例&#xff08;等于没说&#xff09;方案2 在PRO文件中&#xff0c;加上CONFIG console Chapter1 【Qt问题】解决 Cannot retrieve debuggi…

git 提交代码流程

1. 公-->私-->本-->私-->公 缺点&#xff1a;多了一个步骤&#xff0c;就多了一次申请时间&#xff0c;首先在公仓申请合并到私仓&#xff0c;私仓同意合并&#xff0c;获取到公仓最新版本&#xff1b; 优点&#xff1a;不容易污染公仓 2. 公-->本-->私--&…

Java 中的 transient 关键字:深入解析与实战

在 Java 编程中&#xff0c;transient 关键字是一个非常有用的工具&#xff0c;尤其是在处理对象序列化时。尽管 transient 关键字在日常开发中可能不常被使用&#xff0c;但了解它的作用和使用场景对于提升代码的安全性和性能至关重要。本文将深入探讨 transient 关键字的作用…

App渠道来源追踪方案全面分析(iOS/Android/鸿蒙)

一、App 渠道来源追踪概述 渠道来源统计/追踪&#xff0c;其原理都可以称之为归因&#xff0c;归因是用于判断用户在什么原因、什么时间、什么场景下载了 App&#xff0c;以及打通他们在激活 App 后进行的一系列操作&#xff08;比如注册、付费、加购等&#xff09;。 渠道来…

参数跟丢了之JS生成器和包装器

如需转载请注明出处.欢迎小伙伴一起讨论技术. 逆向网址:aHR0cHM6Ly91bmlvbi5qZC5jb20vcHJvTWFuYWdlci9pbmRleD9wYWdlTm89MQ 跟踪接口:aHR0cHM6Ly9hcGkubS5qZC5jb20vYXBp 跟踪参数:h5st 本文目标:记录学习下自定义的生成器和包装器,不做具体的参数加密逻辑分析 直接启动器进…

Redis集群——针对实习面试

目录 Redis集群Redis集群解决了什么问题&#xff1f;Redis集群是如何分片的&#xff1f;什么是Sentinel&#xff1f;Redis如何使用哨兵&#xff08;Sentinel&#xff09;系统&#xff1f;集群如何进行故障转移&#xff1f;Redis集群中的主从复制模型是怎样的&#xff1f;Redis集…

【种完麦子,我就往南走,去西双版纳,过个冬天!】

麦子奶奶&#xff1a;冰哥&#xff0c;你好。 大冰&#xff1a;你好&#xff0c;咱俩不定谁大呢。 麦子奶奶&#xff1a;嗯&#xff0c;我大&#xff0c;我60多了&#xff0c;你各方面都是哥。 大冰&#xff1a;阿姨好 麦子奶奶&#xff1a;我想出去看看祖国的大好河山&…

长亭那个检测能力超强的 WAF,出免费版啦

告诉你们一个震撼人心的消息&#xff0c;那个检测能力超强的 WAF——长亭雷池&#xff0c;他推出免费社区版啦&#xff0c;体验地址见文末。 八年前我刚从学校毕业&#xff0c;在腾讯做安全研究&#xff0c;看到宇森在 BlackHat 上演讲的议题 《永别了&#xff0c;SQL 注入》 …

Elasticsearch+kibana+filebeat的安装及使用

版本7.6.0 自己去官网下载或者私信找我要&#xff0c;jdk是8版本 1.ES安装 网上有好多安装教程可以自己去搜索 这个是我的es文件路径&#xff1a; { “name” : “node-1”, “cluster_name” : “elasticsearch”, “cluster_uuid” : “NIepktULRfepkje3JHw8NA”, “ve…

NVR小程序接入平台/设备EasyNVR多品牌NVR管理工具/设备汇聚公共资源场景方案全析

随着信息技术的飞速发展&#xff0c;视频监控已经成为现代社会安全管理和业务运营不可或缺的一部分。特别是在公共资源管理方面&#xff0c;视频监控的应用日益广泛&#xff0c;涵盖了智慧城市、智能交通、大型企业以及校园安防等多个领域。NVR小程序接入平台EasyNVR作为一款功…

ThingsBoard规则链节点:RPC Call Reply节点详解

引言 1. RPC Call Reply 节点简介 2. 节点配置 2.1 基本配置示例 3. 使用场景 3.1 设备控制 3.2 状态查询 3.3 命令执行 4. 实际项目中的应用 4.1 项目背景 4.2 项目需求 4.3 实现步骤 5. 总结 引言 ThingsBoard 是一个开源的物联网平台&#xff0c;提供了设备管理…

【论文复现】基于图卷积网络的轻量化推荐模型

本文所涉及所有资源均在这里可获取。 &#x1f4d5;作者简介&#xff1a;热爱跑步的恒川&#xff0c;致力于C/C、Java、Python等多编程语言&#xff0c;热爱跑步&#xff0c;喜爱音乐、摄影的一位博主。 &#x1f4d7;本文收录于论文复现系列&#xff0c;大家有兴趣的可以看一看…

sql数据库-DQL-基本查询

目录 举例表emp 查询多个字段 查询整张表所有数据 给字段名起别名&#xff08;更方便阅读&#xff09; 去除重复的数据 举例表emp 查询多个字段 SELECT 字段1,字段2,字段3...FROM 表名; 举例查询emp表中的name&#xff0c;workno&#xff0c;age字段返回 查询整张表所有数据 …

OpenCV通过指针裁剪图像

OpenCV 中mat 格式的像素数值都是连续排列的。为了深入了解cuda 编程。我们来写一个简单的小程序测试一下。 1 不裁剪 cv::Mat crop_image(int(height), int(width), CV_8UC3, image.data);2 只保留图像1/3 cv::Mat crop_image(int(height/3), int(width), CV_8UC3, image.da…