当前位置: 首页 > news >正文

Vue是如何实现nextTick的?

你好同学,我是沐爸,欢迎点赞、收藏和关注。个人知乎

Vue.js 的 nextTick 函数是一个非常重要的功能,它用于延迟执行代码块到下次 DOM 更新循环之后。这在 Vue.js 的异步更新队列机制中非常有用,尤其是在你需要基于更新后的 DOM 来执行某些操作时。

实现原理

Vue.js 的 nextTick 的实现原理主要依赖于 JavaScript 的事件循环和微任务(microtask)或宏任务(macrotask)队列。Vue 使用了一种叫做“异步更新队列”的技术来优化 DOM 的更新。当你修改 Vue 组件的数据时,Vue 不会立即更新 DOM,而是将这些更新任务放入一个队列中,并在同一个事件循环的“下次迭代”中执行它们。这样做的好处是可以批量处理多次数据变化,只进行一次 DOM 更新,从而提高性能。

nextTick 函数允许你指定一个回调函数,这个回调函数会在 DOM 更新完成后被调用。Vue2和Vue3的实现有所不同。

Vue2的实现

Vue2通过判断浏览器环境,选择最适合当前环境的异步任务执行方式,以确保回调函数能够尽快执行,从而提高应用的响应速度和性能。

  1. Promise(如果浏览器支持)
    Vue 会检查是否支持 Promise,并尝试使用 Promise.resolve().then() 来安排回调函数在微任务队列中执行。这是因为微任务会在当前执行栈清空后立即执行,但在宏任务(如 setTimeout)之前。
  2. MutationObserver
    如果 Promise 不可用,Vue 会尝试使用 MutationObserver。MutationObserver API 用于在 DOM 树发生变化时异步执行回调函数。Vue 会创建一个文本节点作为观察目标,并在回调函数中调用你的 nextTick 回调函数。然后,它会改变这个文本节点的某些内容来触发 MutationObserver 的回调。
  3. setImmediate
    如果以上两者都不可用,Vue 会尝试使用 setImmediate(这是一个比 setTimeout 更快的 API,但在大多数环境中不可用)。
  4. setTimeout
    作为最后的回退选项,Vue 会使用 setTimeout 来安排回调函数在宏任务队列中执行。这是所有选项中最慢的,因为它会在浏览器重绘和重排之后执行。

源码:

var timerFunc; // 定时器函数
if (typeof Promise !== 'undefined' && isNative(Promise)) {var p_1 = Promise.resolve();timerFunc = function () { // 1.使用Promise.then()p_1.then(flushCallbacks);if (isIOS)setTimeout(noop);};isUsingMicroTask = true;
} else if (!isIE &&typeof MutationObserver !== 'undefined' &&(isNative(MutationObserver) ||MutationObserver.toString() === '[object MutationObserverConstructor]')) {var counter_1 = 1;var observer = new MutationObserver(flushCallbacks);var textNode_1 = document.createTextNode(String(counter_1));observer.observe(textNode_1, {characterData: true});timerFunc = function () { // 2.使用MutationObservercounter_1 = (counter_1 + 1) % 2;textNode_1.data = String(counter_1);};isUsingMicroTask = true;
} else if (typeof setImmediate !== 'undefined' && isNative(setImmediate)) {timerFunc = function () { // 3.使用setImmediatesetImmediate(flushCallbacks);};
} else {timerFunc = function () { // 4.使用setTimeoutsetTimeout(flushCallbacks, 0);};
}function nextTick(cb, ctx) {var _resolve;callbacks.push(function () {if (cb) {try {cb.call(ctx);}catch (e) {handleError(e, ctx, 'nextTick');}}else if (_resolve) {_resolve(ctx);}});if (!pending) {pending = true;timerFunc(); // 执行定时器}// $flow-disable-lineif (!cb && typeof Promise !== 'undefined') {return new Promise(function (resolve) {_resolve = resolve;});}
}

Vue3的实现

不知道是因为Promise的支持度高,还是Vue3不在兼容低版本的浏览器,Vue3直接使用了Promise.then()这个微任务来处理DOM更新后的回调。

源码:

const resolvedPromise = /* @__PURE__ */ Promise.resolve();
let currentFlushPromise = null;
function queueFlush() {if (!isFlushing && !isFlushPending) {isFlushPending = true;currentFlushPromise = resolvedPromise.then(flushJobs);}
}function nextTick(fn) {const p = currentFlushPromise || resolvedPromise;return fn ? p.then(this ? fn.bind(this) : fn) : p;
}

查看源码可知,Vue3没有再向Vue2那样判断浏览器环境来选择异步任务执行方式,而是直接采用了Promise.then()方法。

希望对你有所帮助,下期再见!

相关文章:

Vue是如何实现nextTick的?

你好同学,我是沐爸,欢迎点赞、收藏和关注。个人知乎 Vue.js 的 nextTick 函数是一个非常重要的功能,它用于延迟执行代码块到下次 DOM 更新循环之后。这在 Vue.js 的异步更新队列机制中非常有用,尤其是在你需要基于更新后的 DOM 来…...

rabbitmq镜像集群搭建

用到的ip地址 ip地址端口192.168.101.65(主)15672192.168.101.7515672192.168.101.8515672 安装erlang和rabbitmq 安装 安装三个包 yum install esl-erlang_23.0-1_centos_7_amd64.rpm -y yum install esl-erlang-compat-18.1-1.noarch.rpm -y rpm -…...

《c++并发编程实战》 笔记

《c并发编程实战》 笔记 1、你好,C的并发世界为什么要使用并发 第2章 线程管理2.1.1 启动线程2.2 向线程函数传递参数2.5 识别线程 第3章 线程间共享数据3.2.1 C中使用互斥量避免死锁的进阶指导保护共享数据的替代设施 第4章 同步并发操作4.1 等待一个事件或其他条件…...

57qi5rW35LqRZUhS pc.mob SQL注入漏洞复现

0x01 产品简介 57qi5rW35LqRZUhS是大中型企业广泛采用人力资源管理系统。某云是国内顶尖的HR软件供应商,是新一代eHR系统的领导者。 0x02 漏洞概述 57qi5rW35LqRZUhS pc.mob 接口存在SQL注入漏洞,未经身份验证的远程攻击者除了可以利用 SQL 注入漏洞获取数据库中的信息(例…...

微信小程序--27(自定义组件4)

一、父子组件之间通信的3种方式 1、属性绑定 用于父组件向子组件的只当属性设置数据,但只能设置JSON兼容的数据 2、事件绑定 用于子组件向父组件传递数据,可以传递任意数据 3、获取组件实例 父组件还可以通过this.select Component()获取子组件的实…...

Linux | Linux进程万字全解:内核原理、进程状态转换、优先级调度策略与环境变量

目录 1、从计算机组成原理到冯诺依曼架构 计算机系统的组成 冯诺依曼体系 思考:为什么计算机不能直接设计为 输入设备-CPU运算-输出设备 的结构? 2、操作系统(Operator System) 概念 设计OS的目的 描述和组织被管理对象 3、进程 基本概念 进程id和父进程…...

VBA技术资料MF184:图片导入Word添加说明文字设置格式

我给VBA的定义:VBA是个人小型自动化处理的有效工具。利用好了,可以大大提高自己的工作效率,而且可以提高数据的准确度。“VBA语言専攻”提供的教程一共九套,分为初级、中级、高级三大部分,教程是对VBA的系统讲解&#…...

在函数设计中应用单一职责原则:函数分解与职责分离

在函数设计中应用单一职责原则:函数分解与职责分离 引言 单一职责原则(Single Responsibility Principle, SRP)是面向对象设计原则中的核心原则之一,强调一个类或函数应该只有一个责任或理由去改变。在函数设计中,应…...

多线程锁机制面试

目录 乐观锁的底层原理 ReentrantLock的实现原理 读写锁 ReentrantReadWriteLock synchronized 底层原理 Lock和synchronized的区别 乐观锁的底层原理 版本号机制 在数据库表中添加一个版本号字段(如 version),每次更新数据时都会将版本号…...

《SQL 中计算地理坐标两点间距离的魔法》

在当今数字化的世界中,地理数据的处理和分析变得越来越重要。当我们面对一个包含地理坐标数据的表时,经常会遇到需要计算两点之间距离的需求。无论是在物流配送路线规划、地理信息系统应用,还是在基于位置的服务开发中,准确计算两…...

微服务可用性设计

一、隔离 对系统或资源进行分割,实现当系统发生故障时能限定传播范围和影响范围。进一步的,通过隔离能够降低系统之间得耦合度,使得系统更容易维护和扩展。某些业务场景下合理使用隔离技巧也能提高整个业务的性能。我理解隔离本质就是一种解…...

【扒代码】dave readme文档翻译

jerpelhan/DAVE (github.com) 摘要 低样本计数器估算选定类别对象的数量,即使在图像中只有少量或没有标注样本的情况下。目前最先进的技术通过对象位置密度图的总和来估算总数量,但这种方法无法提供单个对象的位置和大小,这对于许多应用来说…...

c语言---文件

这一节我准备分三个部分来带领大家了解文件 ——一、有关文件的基础知识 ————二、文件的简单操作 ————————三、文件结束的判定 ————————————四、文件缓冲区 一、文件的基础知识: 首先在了解文件之前,我们需要了解C/C程序内存…...

Windows系统下Go安装与使用

step1: 下载go语言SDK 下载地址:https://go.dev/dl/ 下载后选择合适位置安装即可,我选择D盘 在安装完成后,可以通过go env 命令检测是否安装成功。在“命令提示符”界面输入“go env”命令,如果显示如下类似结果则说明…...

day24-测试之接口测试基础

目录 一、接口的定义 二、接口的优点 三、API接口 四、接口测试流程 五、网络基础概念 六、HTTP和RURL 七、get和post请求 八、数据格式 九、状态码 十、restful风格 十一、接口工具 一、接口的定义 程序之间协作所要遵循的一套规范、标准 二、接口的优点 2.1.责任…...

TSN 交换机

TSN(Time-Sensitive Networking)交换机是一种支持时间敏感网络协议的网络交换设备,用于在以太网网络中实现低延迟、高确定性的数据传输。TSN 是一组 IEEE 802 标准的集合,旨在通过标准化的方式,将传统的以太网扩展到需…...

针对thinkphp站点的漏洞挖掘和经验分享

0x1 前言 浅谈 目前在学习和研究thinkphp相关漏洞的打法,然后最近对于thinkphp资产的收集方面有了一个简单的认识,然后写一篇新手看的thinkphp相关的漏洞收集和挖掘的文章来分享下。然后后面是给师傅们分享下后台文件上传,然后直接打一个ge…...

MySQL数据库入门,pycharm连接数据库—详细讲解

一.安装MySQL 1.常用MySQL5.7,首先安装MySQL, (一) (二) (三) (四) (五) 2.配置环境变量 打开MySQL安装路径,在其中找到…...

.bat文件快速运行vue项目

如何使用bat文件快速运行vue项目? 新建个文件,改名为serve.bat。 在文件中写入以下内容: # cd 项目路径 cd D:\projects\xxx npm run serve pausecd 项目所在的路径 npm run dev/serve ,取决于项目的启动方法,打…...

数据结构(邓俊辉)学习笔记】优先级队列 07——堆排序

1.算法 作为完全二叉堆的一个应用,这节来介绍堆排序算法。 是的,谈到优先级队列,我们很自然地就会联想到排序。因为就其功能而言,包括完全二叉堆在内的任何一种优先级队列都天生地具有选取功能,也就是选取其中的最大…...

多云管理“拦路虎”:深入解析网络互联、身份同步与成本可视化的技术复杂度​

一、引言:多云环境的技术复杂性本质​​ 企业采用多云策略已从技术选型升维至生存刚需。当业务系统分散部署在多个云平台时,​​基础设施的技术债呈现指数级积累​​。网络连接、身份认证、成本管理这三大核心挑战相互嵌套:跨云网络构建数据…...

rknn优化教程(二)

文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK,开始写第二篇的内容了。这篇博客主要能写一下: 如何给一些三方库按照xmake方式进行封装,供调用如何按…...

盘古信息PCB行业解决方案:以全域场景重构,激活智造新未来

一、破局:PCB行业的时代之问 在数字经济蓬勃发展的浪潮中,PCB(印制电路板)作为 “电子产品之母”,其重要性愈发凸显。随着 5G、人工智能等新兴技术的加速渗透,PCB行业面临着前所未有的挑战与机遇。产品迭代…...

电脑插入多块移动硬盘后经常出现卡顿和蓝屏

当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时,可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案: 1. 检查电源供电问题 问题原因:多块移动硬盘同时运行可能导致USB接口供电不足&#x…...

c++ 面试题(1)-----深度优先搜索(DFS)实现

操作系统:ubuntu22.04 IDE:Visual Studio Code 编程语言:C11 题目描述 地上有一个 m 行 n 列的方格,从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子,但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...

华为OD机试-食堂供餐-二分法

import java.util.Arrays; import java.util.Scanner;public class DemoTest3 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseint a in.nextIn…...

【服务器压力测试】本地PC电脑作为服务器运行时出现卡顿和资源紧张(Windows/Linux)

要让本地PC电脑作为服务器运行时出现卡顿和资源紧张的情况,可以通过以下几种方式模拟或触发: 1. 增加CPU负载 运行大量计算密集型任务,例如: 使用多线程循环执行复杂计算(如数学运算、加密解密等)。运行图…...

零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)

本期内容并不是很难,相信大家会学的很愉快,当然对于有后端基础的朋友来说,本期内容更加容易了解,当然没有基础的也别担心,本期内容会详细解释有关内容 本期用到的软件:yakit(因为经过之前好多期…...

return this;返回的是谁

一个审批系统的示例来演示责任链模式的实现。假设公司需要处理不同金额的采购申请,不同级别的经理有不同的审批权限: // 抽象处理者:审批者 abstract class Approver {protected Approver successor; // 下一个处理者// 设置下一个处理者pub…...

STM32HAL库USART源代码解析及应用

STM32HAL库USART源代码解析 前言STM32CubeIDE配置串口USART和UART的选择使用模式参数设置GPIO配置DMA配置中断配置硬件流控制使能生成代码解析和使用方法串口初始化__UART_HandleTypeDef结构体浅析HAL库代码实际使用方法使用轮询方式发送使用轮询方式接收使用中断方式发送使用中…...