透析Vue的nextTick原理

news2025/3/22 8:57:36

nextTick 是 Vue.js 中的一个核心机制,用于在 下一次 DOM 更新周期后 执行回调函数。它的核心原理是 利用 JavaScript 的事件循环机制(Event Loop),结合微任务(Microtask)或宏任务(Macrotask)的调度策略,确保回调在 DOM 更新完成后执行。


核心原理分析

1. DOM 更新的异步性

Vue 的数据驱动视图更新是 异步批量执行 的。当数据变化时,Vue 不会立即更新 DOM,而是开启一个队列,缓冲同一事件循环中的所有数据变更。这样可以避免不必要的重复渲染,提高性能。

2. 回调队列
  • 每次调用 nextTick(callback),Vue 会将 callback 推入一个 回调队列

  • 当需要执行队列时,Vue 会通过 异步任务调度器 触发队列中所有回调的执行。

3. 异步任务优先级

Vue 会优先使用 微任务(Microtask) 实现异步调度(因为微任务会在当前事件循环的末尾执行),但在不支持微任务的环境下会降级为 宏任务(Macrotask)。具体实现策略如下:

  • 现代浏览器:优先使用 Promise.then()(微任务)。

  • 不支持 Promise 的环境:降级到 MutationObserver(微任务)。

  • 其他环境(如旧版 IE):使用 setImmediate 或 setTimeout(fn, 0)(宏任务)。


源码简化逻辑

以下是 Vue 内部 nextTick 的简化实现逻辑:

const callbacks = []; // 回调队列
let pending = false; // 标记是否已向任务队列添加任务

function flushCallbacks() {
  pending = false;
  const copies = callbacks.slice(0);
  callbacks.length = 0; // 清空队列
  for (let i = 0; i < copies.length; i++) {
    copies[i](); // 依次执行回调
  }
}

function nextTick(callback) {
  callbacks.push(() => {
    if (callback) {
      try {
        callback();
      } catch (e) {
        handleError(e);
      }
    }
  });

  if (!pending) {
    pending = true;
    // 根据环境选择异步策略
    if (typeof Promise !== 'undefined') {
      Promise.resolve().then(flushCallbacks);
    } else if (typeof MutationObserver !== 'undefined') {
      // 使用 MutationObserver 模拟微任务
      const observer = new MutationObserver(flushCallbacks);
      const textNode = document.createTextNode(String(counter));
      observer.observe(textNode, { characterData: true });
      textNode.data = String((counter + 1) % 2);
    } else {
      setTimeout(flushCallbacks, 0);
    }
  }
}

关键点总结

  1. 异步批量更新
    Vue 会将同一事件循环中的多个数据变更合并,避免频繁的 DOM 操作。

  2. 微任务优先
    优先使用 Promise.then() 或 MutationObserver 触发回调,确保回调在 当前事件循环的末尾(DOM 更新后)执行。

  3. 降级策略
    根据浏览器特性选择合适的异步 API,确保兼容性。

  4. 回调队列
    所有通过 nextTick 注册的回调会被推入队列,统一在下一个事件循环中执行。


使用场景

// 修改数据后,立即获取更新后的 DOM
this.message = 'Updated';
this.$nextTick(() => {
  console.log(this.$el.textContent); // 输出 'Updated'
});

总结

nextTick 的核心是通过 异步任务队列 和 事件循环机制,确保回调在 DOM 更新完成后执行。这种设计既优化了性能(减少重复渲染),又保证了开发者能在正确时机获取最新的 DOM 状态。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

w264民族婚纱预定系统

&#x1f64a;作者简介&#xff1a;多年一线开发工作经验&#xff0c;原创团队&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的网站项目。 代码可以查看文章末尾⬇️联系方式获取&#xff0c;记得注明来意哦~&#x1f339;赠送计算机毕业设计600个选题excel文…

Compose 实践与探索十五 —— 自定义触摸

1、自定义触摸与一维滑动监测 之前我们在讲 Modifier 时讲过如下与手势检测相关的 Modifier&#xff1a; Modifier.clickable { } Modifier.combinedClickable { } Modifier.pointerInput {detectTapGestures { } }这里对以上内容就不再赘述了&#xff0c;直接去讲解更复杂的…

炫酷的3D按钮效果实现 - CSS3高级特性应用

炫酷的3D按钮效果实现 - CSS3高级特性应用 这里写目录标题 炫酷的3D按钮效果实现 - CSS3高级特性应用项目介绍核心技术实现1. 基础结构设计2. 视觉效果实现2.1 背景渐变2.2 立体感营造 3. 交互动效设计3.1 悬停效果3.2 按压效果 技术要点分析1. 深度层次感2. 动画过渡3. 性能优…

teaming技术

一.介绍 在CentOS 6与RHEL 6系统中&#xff0c;双网卡绑定采用的是bonding技术。到了CentOS 7&#xff0c;不仅能继续沿用bonding&#xff0c;还新增了teaming技术。在此推荐使用teaming&#xff0c;因其在查看与监控方面更为便捷 。 二.原理 这里介绍两种最常见的双网卡绑定…

【JavaEE进阶】Linux常用命令

目录 &#x1f343;前言 &#x1f334;pwd 与 ls &#x1f6a9;pwd &#x1f6a9;ls &#x1f38d;cd &#x1f332;mkdir与touch &#x1f6a9;mkdir &#x1f6a9;touch &#x1f340;cat与rm &#x1f6a9;cat &#x1f6a9;rm &#x1f38b;vim &#x1f6a9;…

【FastGPT】利用知识库创建AI智能助手

【FastGPT】利用知识库创建AI智能助手 摘要创建知识库上传文档创建应用准备提示词准备开场白关联知识库AI回答效果 摘要 关于FastGPT的部署&#xff0c;官方提供了docker-compose方式的部署文档&#xff0c;如果使用的是podman和podman-compose的同学&#xff0c;可以参考这篇…

【DeepSeek 学c++】dynamic_cast 原理

用于向下转化。 父类引用指向指类对象 假设父亲是a, 子类是b. B* pb new B; 子类对象 A* pa 父类引用指向子类对象&#xff0c; 那么向上转化 Apa pb 这个是自动完成的&#xff0c;隐式转化&#xff0c;不需要dynamic_cast 向下转化指的是 A pa new B。 这个是指向子类对象…

【递归,搜索与回溯算法篇】- 名词解释

一. 递归 1. 什么是递归&#xff1f; 定义&#xff1a; 函数自己调用自己的情况关键点&#xff1a; ➀终止条件&#xff1a; 必须明确递归出口&#xff0c;避免无限递归 ➁子问题拆分&#xff1a; 问题需能分解成结构相同的更小的子问题缺点&#xff1a; ➀栈溢出风险&#x…

Beans模块之工厂模块注解模块@Qualifier

博主介绍&#xff1a;✌全网粉丝5W&#xff0c;全栈开发工程师&#xff0c;从事多年软件开发&#xff0c;在大厂呆过。持有软件中级、六级等证书。可提供微服务项目搭建与毕业项目实战&#xff0c;博主也曾写过优秀论文&#xff0c;查重率极低&#xff0c;在这方面有丰富的经验…

数据结构---图的深度优先遍历(DFS)

一、与树的深度优先遍历之间的联系 1.类似于树的先根遍历。 递归访问各个结点&#xff1a; 2.图的深度优先遍历 先设置一个数组&#xff0c;初始值全部设置为false&#xff0c;先访问一个结点&#xff0c;在用一个循环&#xff0c;依次检查和这个结点相邻的其他结点&#xff0c…

健康养生:拥抱生活,从呵护身心开始

在这个瞬息万变的时代&#xff0c;人们好似不停旋转的陀螺&#xff0c;在忙碌中迷失了对健康的关注。然而&#xff0c;健康养生绝非可有可无的点缀&#xff0c;它是幸福生活的基石&#xff0c;如同阳光与空气&#xff0c;滋养并支撑着我们的生命。当我们懂得拥抱健康养生&#…

QT网页显示的几种方法及对比

一.直接跳转打开网页 1.使用QDesktopServices::openUrl调用系统浏览器 原理&#xff1a;直接调用操作系统默认浏览器打开指定URL&#xff0c;不在应用程序内嵌入网页。 优点&#xff1a; 实现简单&#xff0c;无需额外模块或依赖。 适用于仅需跳转外部浏览器的场景。 缺点&…

Linux python 安装 conda(内部自带的有python的版本了)

位置网站 https://repo.anaconda.com/miniconda/也可以在https://www.anaconda.com/download/success 官方下载之后方linux中 切换路径之后 执行 bash Miniconda3-py310_25.1.1-2-Linux-x86_64.sh [rootVM-4-5-centos ~]# [rootVM-4-5-centos ~]# uname -a Linux VM-4-5-cen…

git原理与常用命令及其使用

认识工作区、暂存区、版本库 ⼯作区&#xff1a;是在电脑上你要写代码或⽂件的⽬录。 暂存区&#xff1a;英⽂叫 stage 或 index。⼀般存放在 .git ⽬录下的 index ⽂件&#xff08;.git/index&#xff09;中&#xff0c;我们 把暂存区有时也叫作索引&#xff08;index&#xf…

19681 01背包

19681 01背包 ⭐️难度&#xff1a;中等 &#x1f31f;考点&#xff1a;动态规划、01背包 &#x1f4d6; &#x1f4da; import java.util.Arrays; import java.util.LinkedList; import java.util.Queue; import java.util.Scanner;public class Main {static int N 10001…

Guava:Google开源的Java工具库,太强大了

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家&#xff0c;历代文学网&#xff08;PC端可以访问&#xff1a;https://literature.sinhy.com/#/?__c1000&#xff0c;移动端可微信小程序搜索“历代文学”&#xff09;总架构师&#xff0c;15年工作经验&#xff0c;精通Java编…

蓝桥杯每日一题----海底高铁

&#x1f308;个人主页&#xff1a;羽晨同学 &#x1f4ab;个人格言:“成为自己未来的主人~” 题目链接 P3406 海底高铁 - 洛谷https://www.luogu.com.cn/problem/P3406 解题思路 在这道题来说&#xff0c;主要使用的想法就是使用一维的差分数组&#xff0c;这道题中有两个买…

触动精灵对某东cookie读取并解密--记lua调用C语言

在Mac上构建Lua扩展模块&#xff1a;AES解密与Base64解码实战 今天我要分享一个实用技术&#xff1a;如何在Mac系统上为Lua编写和编译C扩展模块&#xff0c;特别是实现一个某东iOS PIN码解密功能的扩展。这对于需要在Lua环境中执行高性能计算或使用底层系统功能的开发者非常有…

【设计模式】三十二、策略模式

系列文章|源码 https://github.com/tyronczt/design-mode-learn 文章目录 系列文章|源码一、模式定义与核心思想二、模式结构与Java实现1. 核心角色2. Java代码示例 三、策略模式的五大核心优势四、适用场景五、与其他模式的对比六、最佳实践建议总结 &#x1f680;进阶版【更…

Cyberchef实用功能之-json line格式文件美化和查询

本文将介绍一下如何使用cyberchef对json line格式数据进行美化方便阅读&#xff0c;以及json line格式数据的批量查询操作。 之前的文章介绍了json格式数据的美化和查询&#xff0c;即Cyberchef实用功能之-json解析美化和转换&#xff0c;Cyberchef实用功能之-批量提取json数据…