根据源码分析vue中nextTick的实现原理
根据源码分析vue中nextTick的实现原理
- 一. 核心变量定义
- 二. 异步策略选择(降级处理)
- 1. 微任务优先
- 2. 降级到 MutationObserver
- 3. 降级到宏任务
- 三、回调执行逻辑
- 四、 nextTick 函数实现
- 五、 与 Vue 更新流程的结合
- 六、关键设计思想
- 七、实现原理总结
- 1. 队列管理:
- 2. 异步调度:
- 3. 执行顺序:
从
Vue 2.x
源码(
src/core/util/next-tick.js
)的角度,深入分析
nextTick
的实现原理。以下是关键代码逻辑的分步解析:
一. 核心变量定义
const callbacks = []; // 回调队列
let pending = false; // 是否正在等待异步执行的标记
let timerFunc; // 异步调度函数
callbacks
存储所有待执行的回调函数。pending
防止多次触发异步任务。timerFunc
根据不同环境动态赋值为最优的异步方法(微任务或宏任务)。
二. 异步策略选择(降级处理)
Vue
根据环境选择最高效的异步方式,优先级为 微任务 > 宏任务:
1. 微任务优先
if (typeof Promise !== 'undefined' && isNative(Promise)) {const p = Promise.resolve();timerFunc = () => {p.then(flushCallbacks);// iOS UIWebView 的 Promise.then 可能不触发,强制宏任务兜底if (isIOS) setTimeout(noop);};isUsingMicroTask = true; // 标记为微任务
}
- 优先使用
Promise.then
(微任务),确保回调在DOM
更新后立即执行。 - 针对
iOS UIWebView
的特殊修复(微任务可能不触发)。
2. 降级到 MutationObserver
else if (!isIE && typeof MutationObserver !== 'undefined' && (isNative(MutationObserver) ||MutationObserver.toString() === '[object MutationObserverConstructor]'
)) {let counter = 1;const textNode = document.createTextNode(String(counter));const observer = new MutationObserver(flushCallbacks);observer.observe(textNode, { characterData: true });timerFunc = () => {counter = (counter + 1) % 2;textNode.data = String(counter); // 触发 MutationObserver};isUsingMicroTask = true;
}
- 监听
DOM
节点变化触发微任务(非 IE 环境)。
3. 降级到宏任务
else if (typeof setImmediate !== 'undefined' && isNative(setImmediate)) {timerFunc = () => setImmediate(flushCallbacks);
} else {timerFunc = () => setTimeout(flushCallbacks, 0);
}
setImmediate(Node.js)
或 setTimeout
(浏览器)兜底。
三、回调执行逻辑
function flushCallbacks() {pending = false; // 重置标记,允许下次调度const copies = callbacks.slice(0); // 复制队列,避免执行时新回调污染callbacks.length = 0; // 清空原队列for (let i = 0; i < copies.length; i++) {copies:ml-search[i]; // 依次执行回调}
}
- 复制队列:防止回调中再次调用
nextTick
导致死循环。 - 清空原队列:确保同一批回调只执行一次。
四、 nextTick 函数实现
export function nextTick(cb?: Function, ctx?: Object) {let _resolve;callbacks.push(() => {if (cb) {try {cb.call(ctx); // 执行用户传入的回调} catch (e) {handleError(e, ctx, 'nextTick');}} else if (_resolve) {_resolve(ctx); // 支持 Promise 化调用}});if (!pending) {pending = true; // 标记为等待执行timerFunc(); // 触发异步调度}// 支持 Promise 链式调用if (!cb && typeof Promise !== 'undefined') {return new Promise(resolve => {_resolve = resolve; // 保存 resolve 函数供回调触发});}
}
- 将回调推入队列:用户传入的回调被包装后存入
callbacks
。 - 触发异步调度:若未在等待中,调用
timerFunc
异步执行回调。 Promise
支持:当不传cb
时返回Promise
,便于链式调用。
五、 与 Vue 更新流程的结合
在 Vue
的 异步更新队列 中,数据变化触发的 DOM
更新会被合并到同一事件循环:
// src/core/observer/scheduler.js
function queueWatcher(watcher: Watcher) {const id = watcher.id;if (!flushing) {queue.push(watcher); // 将 Watcher 推入队列}if (!waiting) {waiting = true;nextTick(flushSchedulerQueue); // 异步执行队列刷新}
}
flushSchedulerQueue
:执行所有Watcher
的run
方法,更新DOM
。- 用户通过
nextTick
注册的回调 会在flushSchedulerQueue
之后执行,确保能访问最新DOM
。
六、关键设计思想
- 批量执行:同一事件循环内的所有数据变更和
nextTick
回调合并执行。 - 异步优先级:微任务优先(更快),宏任务兜底(兼容性)。
- 状态隔离:通过
pending
和队列复制避免递归调用问题。
this.message = 'updated';
Vue.nextTick(() => {console.log('DOM updated:', this.$el.textContent); // 正确拿到最新 DOM
});
数据变更触发 Watcher
队列更新,nextTick
回调在队列刷新后执行。
七、实现原理总结
通过源码分析,nextTick 的核心实现逻辑是:
1. 队列管理:
合并同一事件循环内的回调。
2. 异步调度:
优先微任务(Promise/MutationObserver
),降级宏任务(setImmediate/setTimeout
)。
3. 执行顺序:
确保 DOM 更新队列先于用户回调执行。
相关文章:
根据源码分析vue中nextTick的实现原理
根据源码分析vue中nextTick的实现原理 一. 核心变量定义二. 异步策略选择(降级处理)1. 微任务优先2. 降级到 MutationObserver3. 降级到宏任务 三、回调执行逻辑四、 nextTick 函数实现五、 与 Vue 更新流程的结合六、关键设计…...
Linux内核TCP/IP协议栈中的设计模式:从面向对象到系统级软件的跨界实践
引言 设计模式(Design Patterns)自GoF(Gang of Four)在1994年提出以来,已成为软件工程领域的核心概念。尽管其经典定义基于面向对象编程(OOP),但设计模式的本质是解决复杂问题的经验总结,而非局限于特定编程范式。本文以Linux内核的TCP/IP协议栈为例,探讨设计模式在…...
风云可测:华为AI天气大模型将暴雨预测误差缩至3公里内
华为云正式发布全球首个气象专用人工智能大模型"盘古气象",实现台风路径24小时预测误差<30公里、暴雨落区72小时精度91%,较传统数值预报效率提升10000倍。本文基于对西北太平洋10个台风回溯测试、全国2360个气象站验证数据,解析…...
DeepSeek-R1 面试题汇总
Deepseek-r1 面试宝典 原文地址:https://articles.zsxq.com/id_91kirfu15qxw.html DeepSeek-R1 面试题汇总 DeepSeek-R1 面试题汇总 GRPO(Group Relative Policy Optimization)常见面试题汇总篇 DeepSeek-R1 DeepSeek-R1-Zero 常见面试题汇总…...
ASM1042A型CANFD芯片通信可靠性研究
摘要 本文旨在深入探讨ASM1042A型CAN-FD芯片在多节点通信中的可靠性表现。通过对芯片的电气特性、测试环境、多节点通信测试结果等多方面进行分析,结合实验数据与理论研究,全面评估其在复杂通信场景下的性能与可靠性。研究结果表明,ASM1042A…...
Java8 到 Java21 系列之 Stream API:数据处理的新方式(Java 8)
Java 8 到 Java 21 系列之 Stream API:数据处理的新方式(Java 8) 系列目录 Java8 到 Java21 系列之 Lambda 表达式:函数式编程的开端(Java 8)Java 8 到 Java 21 系列之 Stream API:数据处理的…...
【每日一个知识点】分布式数据湖与实时计算
在现代数据架构中,分布式数据湖(Distributed Data Lake) 结合 实时计算(Real-time Computing) 已成为大数据处理的核心模式。数据湖用于存储海量的结构化和非结构化数据,而实时计算则确保数据能够被迅速处理…...
接口自动化学习三:参数化parameterize
使用parametrize之前: def add(x,y):return xy class TestAddFunction(object):def test01(self):resadd(2,4)assert 6resdef test02(self):resadd(4,6)assert 10resparametrize参数化之后: import pytest def add(x,y):return xydata[(10,20,30),(200…...
呼叫中心系统压力测试文档
前期准备 用户需要准备两台配置相同的服务器,A服务器和B服务器。我们在这两台服务器上部署相同授权的程序。 配置流程 1. 创建话术 A服务器和B服务器都需要创建压力测试放音的话术,用于放音。按图操作: 2. 线路和线路组配置 A服务器&am…...
从0开始的构建的天气预报小时钟(基于STM32F407ZGT6,ESP8266 + SSD1309)——第1章 简单的介绍一下ESP8266和他的编程指令
目录 ESP8266编程指令前导——三种工作模式 ESP8266编程指令 工作确认指令(用于非穿透模式下) 设置工作模式:ATCWMODEX 两个重要的复位 硬复位ATRESTORE 软复位ATRST 加入Wifi ATCWJAP 开始一次TCP通信 进入和退出穿透模式 进入 ES…...
Cadence Integrity 3D-IC的解密
Early System-Level Analysis and Signoff Flow 请看下期发布...
清晰易懂的 Flutter 开发环境搭建教程
Flutter 是 Google 推出的跨平台应用开发框架,支持 iOS/Android/Web/桌面应用开发。本教程将手把手教你完成 Windows/macOS/Linux 环境下的 Flutter 安装与配置,从零到运行第一个应用,全程避坑指南! 一、安装 Flutter SDK 1. 下载…...
NO.63十六届蓝桥杯备战|基础算法-⼆分答案|木材加工|砍树|跳石头(C++)
⼆分答案可以处理⼤部分「最⼤值最⼩」以及「最⼩值最⼤」的问题。如果「解空间」在从⼩到⼤的「变化」过程中,「判断」答案的结果出现「⼆段性」,此时我们就可以「⼆分」这个「解空间」,通过「判断」,找出最优解。 这个「⼆分答案…...
Python星球日记 - 第1天:欢迎来到Python星球
🌟引言: 上一篇:Python星球日记专栏介绍(持续更新ing) 名人说:莫听穿林打叶声,何妨吟啸且徐行。—— 苏轼《定风波莫听穿林打叶声》 创作者:Code_流苏(CSDN)(一个喜欢古诗…...
去中心化交易所(DEX)
核心概念与DEX类型 DEX vs CEX 中心化交易所(CEX)风险:资产托管风险(如2019年超2.9亿美元被盗)、隐私泄露(如50万用户信息泄漏)。 DEX优势:用户自持资产(非托管&#x…...
HTTP数据传输的几个关键字Header
本文着重针对http在传输数据时的几种封装方式进行描述。 1. Content-Type(描述body内容类型以及字符编码) HTTP的Content-Type用于定义数据传输的媒体类型(MIME类型),主要分为以下几类: (一)、基础文本类型 text/plain …...
Redis 的 Raft 选举协议
Redis 的 Raft 选举协议 主要用于 Redis Sentinel 和 Redis Cluster 的高可用实现中(尽管 Redis Cluster 默认使用类似 Gossip 的协议,但 Raft 的思想在 Sentinel 的领导者选举中有体现)。以下是关于 Raft 协议在 Redis 中的应用及脑裂问题的详细解析: 一、Redis 中的 Raft…...
sshd启动报错“Failed to start OpenSSH Server daemon”
“systemctl restart sshd”启动sshd服务异常,报错“Failed to start OpenSSH Server daemon”。 使用sshd -t命令检查sshd配置文件,返回关键信息gssapikexalgorithms相关错误。 解决方法 禁用 GSSAPI 相关的 KEX 算法 编辑sshd配置文件,注…...
MIT6.828 Lab3-2 Print a page table (easy)
实验内容 实现一个函数来打印页表的内容,帮助我们更好地理解 xv6 的三级页表结构。 修改内容 kernel/defs.h中添加函数声明,方便其它函数调用 void vmprint(pagetable_t);// lab3-2 Print a page tablekernel/vm.c中添加函数具体定义 采用…...
AI本地部署之ragflow
Ubunturagflowdeepseek本地部署目录 一、配置说明1. 软件配置说明2. 硬件配置说明 二、RagFlow安装和部署1. 前置条件2. 安装注:如果发现没有出现这个界面,可以进入ragflow/docker/ragflow-logs这个路径,查看ragflow_server.log文件中的内容&…...
源码分析之Leaflet属性控件Control.Attribution实现原理
概述 Control.Attribution 是一个 Leaflet 地图控件,用于显示地图的版权信息。它可以显示地图提供者的名称和链接,以及地图上的图层的版权信息。 源码分析 源码实现 Control.Attribution的源码实现如下 var ukrainianFlag <svg aria-hidden"…...
NO.62十六届蓝桥杯备战|基础算法-二分查找|查找元素的第一个和最后一个位置|牛可乐和魔法封印|A-B数对|烦恼的高考意愿(C++)
⼆分算法是我觉得在基础算法篇章中最难的算法。⼆分算法的原理以及模板其实是很简单的,主要的难点在于问题中的各种各样的细节问题。因此,⼤多数情况下,只是背会⼆分模板并不能解决题⽬,还要去处理各种乱七⼋糟的边界问题 34. 在…...
开源模型应用落地-Qwen2.5-Omni-7B模型-部署 “光速” 指南
一、前言 2025年3月,阿里巴巴通义千问团队开源的全模态大模型Qwen2.5-Omni-7B,犹如一记惊雷划破AI领域的长空。这个仅70亿参数的"小巧巨人",以端到端的架构实现了对文本、图像、音频、视频的全模态感知,更通过创新的Thinker-Talker双核架构,将人类"接收-思…...
顺序容器 -forward list单链表
forward list单链表是C11加入到STL的。 使用forward list,必须包含头文件<forward_list> #include <forward_list> 这个头文件被定义在命名空间std内。 namespace std {template <typename T,typename Allocator allocator<T> >class …...
C++:算术运算符
程序员Amin 🙈作者简介:练习时长两年半,全栈up主 🙉个人主页:程序员Amin 🙊 P S : 点赞是免费的,却可以让写博客的作者开心好久好久😎 📚系列专栏:Java全…...
缺页异常导致的iowait打印出相关文件的绝对路径
一、背景 在之前的博客 增加等IO状态的唤醒堆栈打印及缺页异常导致iowait分析-CSDN博客 里,我们进一步优化了D状态和等IO状态的事件的堆栈打印,补充了唤醒堆栈打印,也分析了一种比较典型的缺页异常filemap_fault导致的iowait的情况。 在这篇…...
【Centos】centos7内核升级-亲测有效
相关资源 通过网盘分享的文件:脚本升级 链接: https://pan.baidu.com/s/1yrCnflT-xWhAPVQRx8_YUg?pwd52xy 提取码: 52xy –来自百度网盘超级会员v5的分享 使用教程 将脚本文件上传到服务器的一个目录 执行更新命令 yum install -y linux-firmware执行脚本即可 …...
多模态模型:专栏概要与内容目录
文章目录 多模态模型📚 核心内容模块Stable Diffusion基础教程Stable Diffusion原理深度解析部署与环境配置其他多模态模型实践 多模态模型 🔥 专栏简介 | 解锁AI绘画与多模态模型的技术奥秘 探索多模态AI技术,掌握Stable Diffusion等流行框…...
1. 购物车
1. 购物车 咱们购物车基于 V2 装饰器进行开发,底气来源于 自定义组件混用场景指导 1.1. 素材整合 observedv2和Trace 数据模型和页面 // 其他略 // 购物车 export interface CartGoods {count: number;id: string;name: string;picture: string;price: number;…...
frp 让服务器远程调用本地的服务(比如你的java 8080项目)
1、服务器上安装frp 2、本地安装frp 服务器上 frps.toml 配置信息: bindPort 30000auth.token "密码" # 客户端连接密码vhostHTTPPort 8082 本地 frpc.toml serverAddr "服务器ip" serverPort 30000 auth.token "服务器上设置的…...
《AI大模型应知应会100篇》第56篇:LangChain快速入门与应用示例
第56篇:LangChain快速入门与应用示例 前言 最近最火的肯定非Manus和OpenManus莫属,因为与传统AI工具仅提供信息不同,Manus能完成端到端的任务闭环。例如用户发送“筛选本月抖音爆款视频”,它会自动完成: 爬取平台数据…...
大模型——如何在本地部署微软的OmniParser V2
微软的 OmniParser V2 是一款尖端的人工智能屏幕解析器,可通过分析屏幕截图从图形用户界面中提取结构化数据,使人工智能代理能够与屏幕元素进行无缝交互。该工具是构建自主图形用户界面代理的完美选择,它改变了自动化和工作流程优化的游戏规则。在本指南中,我们将介绍如何在…...
Oracle触发器使用(一):DML触发器
Oracle触发器使用(一):DML触发器 DML触发器条件谓词触发器INSTEAD OF DML触发器复合DML触发器Oracle数据库中的触发器(Trigger)本质上也是PL/SQL代码,触发器可以被Enable或者Disable,但是不能像存储过程那样被直接调用执行。 触发器不能独立存在,而是定义在表、视图、…...
智慧园区大屏如何实现全局监测:监测意义、内容、方式
智慧园区的价值不容小觑呀,可以说园区的大部分数据都在这个大屏上,监测数据越多,那么大屏的价值就越大。很多小伙伴拿到需求后感觉无从下手,本文在这里智慧园区大屏可以监测哪些内容、监测的意义、监测的方式等,欢迎点…...
LeetCode 解题思路 31(Hot 100)
解题思路: 递归参数: 字符串 s、结果集 result、当前路径 path、回文子串数组 dp、开始位置 start。递归过程: 当当前路径 path 的长度等于 s.length() 时,说明已经分割完成,加入结果集。若当前起止位置满足回文条件…...
fastAPI详细介绍以及使用方法
FastAPI是一个现代的Python web框架,它提供快速构建API的能力。它具有高性能、易用性和文档自动生成的特点,使得开发者能够快速开发高效的API服务。 以下是一些FastAPI的主要特点和优势: 快速:FastAPI基于Python 3.6的异步框架St…...
数字人训练数据修正和查看 不需要GPU也能运行的DH_live-加载自己训练-
自己训练模pth报错 le "D:\ai\dh_live\app.py", line 42, in demo_mini interface_mini(asset_path, wav_path, output_video_name) File "D:\ai\dh_live\demo_mini.py", line 21, in interface_mini renderModel_mini.loadModel("checkpoi…...
WGAN-GP 原理及实现(pytorch版)
WGAN-GP 原理及实现 一、WGAN-GP 原理1.1 WGAN-GP 核心原理1.2 WGAN-GP 实现步骤1.3 总结二、WGAN-GP 实现2.1 导包2.2 数据加载和处理2.3 构建生成器2.4 构建判别器2.5 训练和保存模型2.6 图片转GIF一、WGAN-GP 原理 Wasserstein GAN with Gradient Penalty (WGAN-GP) 是对原…...
chromium魔改——navigator.webdriver 检测
chromium源码官网 https://source.chromium.org/chromium/chromium/src 说下修改的chromium源码思路: 首先在修改源码过检测之前,我们要知道它是怎么检测的,找到他通过哪个JS的API来做的检测,只有知道了如何检测,我们…...
Sentinel[超详细讲解]-7 -之 -熔断降级[异常比例阈值]
📖 主要讲解熔断降级之 --- 异常比例阈值 🚀 1️⃣ 背景 Sentinel 以流量作为切入点,提供了很多的丰富的功能,例如🤗: 流量控制,熔断降级等,它能够有效的适用各个复杂的业务场景&am…...
程序化广告行业(56/89):S2S对接与第三方广告监测全解析
程序化广告行业(56/89):S2S对接与第三方广告监测全解析 大家好!在前面的博客中,我们一起深入学习了程序化广告的人群标签、用户标签生成、Look Alike原理,以及DMP与DSP对接和数据统计原理等内容。今天&…...
C++进阶知识复习 31~38
目的 写这一系列文章的目的主要是为了秋招时候应对计算机基础问题能够流畅的回答出来 (如果不整理下 磕磕绊绊的回答会被认为是不熟悉) 本文章题目的主要来源来自于 面试鸭 部分面试鸭上没有而牛客网上有的博主会进行查缺补漏 题目编号按照面试鸭官网…...
Spring Boot 整合mybatis
2025/4/3 向全栈工程师迈进!!! 配置文件在实际开发中如何使用呢,接下去将通过Spring Boot整合mybatis来看配置文件如何在实际开发中被使用。 一、引入mybatis起步依赖 在pom.xml中引入mybatis的起步依赖,如下。 在这…...
新能源汽车测试中的信号调理模块:从原理到实战应用
摘要 信号调理模块(Signal Conditioning Module, SCM)是新能源汽车(NEV)测试系统中的关键环节,直接影响数据采集的精度与可靠性。本文面向HIL测试工程师、电机测试工程师及整车动力经济性测试工程师,系统性…...
一篇关于Netty相关的梳理总结
一篇关于Netty的梳理总结 一、Netty1.1 什么是netty?为什么要用netty1.2 Netty是什么? 二、Netty关于网络基础2.1 线程池2.2 线程池线程的生命周期和状态2.3 为什么要使用线程池2.4 简述线程池原理,FixedThreadPool用的阻塞队列是什么2.5 并发…...
纺织车间数字化转型:降本增效新路径
在纺织行业竞争日益激烈的当下,如何提升生产效率、降低成本成为企业关注的焦点。某纺织车间通过创新引入明达技术MBox20网关并部署IOT 平台,成功接入千台设备,实现了生产模式的重大变革。 以往,纺织车间生产犹如黑箱,…...
递归典例---汉诺塔
https://ybt.ssoier.cn/problem_show.php?pid1205 #include<bits/stdc.h> #define endl \n #define pii pair<int,int>using namespace std; using ll long long;void move(int n,char a,char b,char c) // n 个盘子,通过 b,从 a 移动到 …...
Unity2D:从零开始制作一款跑酷游戏!
目录 成品展示 美术资源 制作步骤 场景预布设: 实现人物基础功能: 移动背景——横向卷轴: 生成障碍物: 生成敌人与攻击逻辑: UI制作与重新开始: 导出游戏: 小结 大家小时候都玩过《…...
维拉工时自定义字段:赋能项目数据的深度洞察 | 上新预告
原文链接:维拉工时自定义字段:赋能项目数据的深度洞察 | 上新预告 在项目管理实践中,每个企业都有独特的数据统计与分析需求。为了帮助用户实现个性化数据建模,从而更精准地衡量项目进度和预算投入,维拉工时全新升级的…...
C++ | 文件读写(ofstream/ifstream/fstream)
一、C文件操作核心类 C标准库通过<fstream>提供了强大的文件操作支持,主要包含三个关键类: 类名描述典型用途ofstream输出文件流(Output File Stream)文件写入操作ifstream输入文件流(Input File Stream&#…...