vue $nextTick 实现原理

nextTick的实现

  • 一:nextTick介绍
  • 二:手写nextTick
  • 三:具体代码
  • 四:实现细节

一:nextTick介绍

nextTick 是 Vue.js 框架中的一个方法,它允许延迟执行一个函数,直到 DOM 更新完成。当你修改了数据并且希望基于更新后的 DOM 来执行某些操作时,nextTick就非常有用了。

在 Vue 中,当更改响应式数据时,Vue 会异步地执行 DOM 更新。这意味着,如果你立即尝试访问或操作刚刚被改变的数据所影响的 DOM 元素,那么可能还没有完成更新。nextTick 就是用来解决这个问题的,它会在下一个 DOM 更新周期后调用回调函数,确保能获取到最新的 DOM 状态。

下面用一个简单的例子来说明如何使用 nextTick:

// 假设此处有一个 Vue 实例和一个元素需要在数据变化后进行处理
new Vue({el: '#app',data: {message: 'Hello'},methods: {updateMessage() {this.message = 'Updated message';// 这里直接访问 DOM 可能不会得到更新后的状态// 因为 DOM 更新是异步的// 使用 nextTick 来确保 DOM 已经更新this.$nextTick(() => {// 在这个回调中,DOM 已经更新到了最新状态console.log(document.querySelector('#message').textContent); // 应该输出 "Updated message"});}}
});// HTML 模板
<div id="app"><p id="message">{{ message }}</p><button @click="updateMessage">Update Message</button>
</div>

在这个例子中,当点击按钮触发 updateMessage 方法时,message 数据会被更新。由于 DOM 更新是异步的,直接在数据更新之后访问 DOM 不一定会看到变化。但是通过 this.$nextTick,我们可以保证在 DOM 完成更新之后再执行回调函数内的代码。

需要注意的是,nextTick 并不只用于 Vue.js,类似的机制也存在于其他一些 JavaScript 库和框架中,比如 React 的 useEffect 钩子也可以用来实现类似的功能。不过在 Vue 中,nextTick 提供了一个更直接的方式来处理这种情况。

二:手写nextTick

想要实现nextTick,以下是我们需要关注的点

  1. DOM 更新是异步的: 浏览器在处理 JavaScript 时,通常会将 DOM 操作放入一个队列中,并且在当前任务完成后才会执行这些操作。这意味着如果修改了一个数据模型并立即尝试访问更新后的 DOM,可能看不到最新的更改,因为 DOM 更新还没有发生。
  2. Promise 和异步执行: 通过返回一个 Promise,这段代码可以等待直到 DOM 更新完成后再解决这个 Promise。这样,可以使用 .then() 或 await 来确保你的代码在 DOM 更新后执行。
  3. MutationObserver 的作用: MutationObserver 是一种可以用来监听 DOM 树变化的 API。它允许在特定节点或整个文档上设置观察者,当被观察的节点发生变化(如属性改变、子节点添加/删除等)时,MutationObserver 会触发回调函数。当使用 MutationObserver 并调用其 observe 方法时,这个观察者会被安排在下一个微任务队列中运行。这与 Vue 的 nextTick 类似,后者也是利用了微任务机制来确保在下一次 DOM 更新循环之后执行代码。

三:具体代码

function nextTick(fn) {return new Promise((resolve, reject) => {// DOM更新完成否?if (typeof MutationObserver !== 'undefined') {//考虑到可能部分浏览器不能兼容MutationObserverconst observer = new MutationObserver(() => {let res = fn()if (res instanceof Promise) {res.then(resolve)} else {resolve()}})        observer.observe(document.getElementById('app'), { attributes: true, childList: true, subtree: true })}})}

四:实现细节

  • 创建 MutationObserver
    • new MutationObserver(callback) 创建一个新的观察者实例。
    • observer.observe(target, options) 开始观察指定的目标元素和选项。上述代码中,目标是 document.getElementById(‘app’),并且设置了 attributes: true, childList: true, subtree: true 以监听所有相关的变化。
  • 回调函数:
    • 当观察到任何变化时,回调函数会被调用。
    • 在回调函数中,执行传入的 fn 函数。
    • 如果 fn 返回的是一个 Promise,则等待该 Promise 解决后再解决外部的 Promise;否则直接解决外部的 Promise。

这里面试官可能会问nextTick是宏任务还是微任务,虽然MutationObserver观察者会被安排在下一个微任务队列中运行,但并不代表nextTick就是一个微任务,当回调函数中执行的函数是一个异步代码时,nextTick里面的promise状态需要等待内部回调中的异步函数返回的peomise状态变更完成后,才能变更,此时nextTick就是一个宏任务

总的来说,这个方式是利用了 MutationObserver 来捕捉 DOM 更新,从而提供了一种机制,可以在 DOM 更新完成后执行一些操作。这种方法并不依赖于 Vue.js 或其他框架,而是基于标准的 Web API,因此具有很好的兼容性和通用性,可以作为一个跨平台的解决方案,用于需要在 DOM 更新后执行某些逻辑的场景。

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

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

相关文章

python-qq定时自动消息发送

预设 qq需要可以enter发送消息 发qq表情代码需要开启快捷表情 import sys import win32gui import win32con import win32clipboard as w import win32api import time import subprocess import datetime import webbrowser import tkinter as tk vb_file_path "./op…

探索迷宫的奥秘:用 C++ 打造你的迷宫游戏之旅!

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…

面试官:重量级锁的8连问,你能接住几个?

前言 接上一篇偏向锁的十连问&#xff0c;继续升级到重量级锁的进阶版&#xff0c;检验一下自己离精通重量级锁还有多远。建议在读之前了解下Java中重量级锁的实现原理。 重量级锁的ObjectMonitor和JUC中的AQS有什么异同 为什么ObjectMonitor需要cxq和entryList两个等待队列 …

AUTOSAR_EXP_ARAComAPI的5章笔记(15)

☞返回总目录 相关总结&#xff1a;AutoSar AP CM服务接口级别的数据类型总结 5.5 服务接口级别的数据类型 以下章节描述了在ara::com中服务接口用户定义数据类型的 C 语言映射。这里的 “用户定义” 是指那些不是由ara::com API 定义&#xff08;例如InstanceIdentifier、F…

2024前端面试题-1.自我介绍+常见考点汇总

一、自我介绍模板 个人信息教育背景工作经验技能专长优势特点 &#xff08;注&#xff1a;括号&#xff09;内的内容可视具体情况决定说不说。以下内容仅为个人想法&#xff0c;仅供参考交流&#xff0c;不喜勿喷&#xff0c;感谢留情~* 1、个人信息&#xff1a; 姓名&…

Leetcode 3325. Count Substrings With K-Frequency Characters I

Leetcode 3325. Count Substrings With K-Frequency Characters I 1. 解题思路2. 代码实现 题目链接&#xff1a;3325. Count Substrings With K-Frequency Characters I 1. 解题思路 这一题思路上就是一个滑动窗口。 我们考察窗口的左边界依次为0到n-1时右边界能够取到的最…

数据结构编程实践20讲(Python版)—19字典树

本文目录 19 字典树&#xff08;Trie&#xff09;S1 说明字典树结构字典树的构建与查找字典树的特点字典树的应用领域 S2 示例S3 应用1&#xff1a;基于 big.txt 实现单词的自动补全功能S3 应用2&#xff1a;实现 IP 路由中的最长前缀匹配S3 应用3&#xff1a;基于 Trie 的压缩…

THP4 SOP16 芯片 高速光耦芯片

光电耦合器输入端加电信号使发光源发光&#xff0c;光的强度取决于激励电流的大小&#xff0c;此光照射到封装在一起的受光器上后&#xff0c;因光电效应而产生了光电流&#xff0c;由受光器输出端引出&#xff0c;这样就实现了电一光一电的转换。 由于光耦合器输入输出间互相…

防火墙和堡垒机有什么区别?

防火墙和堡垒机在网络安全领域都扮演着至关重要的角色,但它们在功能、部署位置、作用范围等方面存在显著差异。 一、功能定位 防火墙:防火墙是一种网络安全系统,主要作用是在私有网络与公网之间建立一道安全屏障,监控和控制网络流量。它通过预定义的安全规则,决定哪些数…

5g工业路由器最新案例:高原气象站网络升级项目

背景&#xff1a; 某省气象局决定在高原地区升级其气象观测网络&#xff0c;以提高天气预报的准确性和及时性&#xff0c;同时为气候变化研究提供更可靠的数据支持。该项目面临以下挑战&#xff1a; 需要在高原广袤且地形复杂的区域部署大量自动气象站&#xff0c;要求网络覆…

【Excel】【VB和JS】表格内容姓名、卡号、身份证敏感信息转换为图片打印

VB代码&#xff1a; Function ConvertCellToImageAndPlace(n As Long, m As Long)Dim sourceCell As RangeSet sourceCell Sheets("Sheet2").Cells(n, m)sourceCell.CopyPicture Appearance:xlScreen, Format:xlPictureDim targetCell As RangeSet targetCell She…

优化SQL查询的最佳实践:提升数据库性能的关键

SQL 查询是数据库操作的核心&#xff0c;特别是当数据量庞大时&#xff0c;性能问题尤为明显。优化 SQL 查询不仅能减少响应时间&#xff0c;还能提高系统整体的可伸缩性。本文将从索引、查询结构、数据库设计和缓存等方面详细介绍如何优化 SQL 查询以提升性能。 一、索引的使…

kotlin 中 ::class ::class.java 和 .javaClass 区别

在 Kotlin 中&#xff0c;获取一个类的类对象&#xff08;Class 对象&#xff09;有几种不同的方式&#xff0c;包括 ::class、::class.java 和 .javaClass。每种方式都有其特定的用途和适用场景。下面是对这三种方式的详细解释&#xff1a; ::class 用途&#xff1a;获取 Kotl…

Java配置 Redis 连接互斥锁或队列预先加载缓存

学习总结 1、掌握 JAVA入门到进阶知识(持续写作中……&#xff09; 2、学会Oracle数据库入门到入土用法(创作中……&#xff09; 3、手把手教你开发炫酷的vbs脚本制作(完善中……&#xff09; 4、牛逼哄哄的 IDEA编程利器技巧(编写中……&#xff09; 5、面经吐血整理的 面试技…

【HuggingFace 如何上传数据集 (2) 】国内网络-稳定上传图片、文本等各种格式的数据

【HuggingFace 下载】diffusers 中的特定模型下载&#xff0c;access token 使用方法总结【HuggingFace 下载中断】Git LFS 如何下载指定文件、单个文件夹&#xff1f;【HuggingFace 如何上传数据集】快速上传图片、文本等各种格式的数据 上文的方法因为是 https 协议&#xf…

CIM系统:智慧城市的数字基石

计算机集成制造系统&#xff08;CIM&#xff09;是智慧城市建设中的关键技术&#xff0c;它通过集成多种信息技术&#xff0c;为城市提供一个全面的数字化镜像。CIM系统不仅涉及建筑信息模型&#xff08;BIM&#xff09;、地理信息系统&#xff08;GIS&#xff09;、物联网&…

1024-过去一年的总结

目录 前言 (10月-24.01)故事的开始 &#xff08;2月-7月&#xff09;漫长的学习与探索 &#xff08;8月-现在&#xff09;低谷期 自我审视 前言 1024在即,就借此机会讲一讲过去一年的经历&#xff0c;也算是全方位总结一下自己 (10月-24.01)故事的开始 那就从去年大一入学…

前端优化:从Vue/React/Svelte的数组更新->渲染策略剖析数组大列表数据展示优化策略

在现代前端框架中&#xff0c;数组的渲染是一个重要的功能。不同的框架在处理数组的操作&#xff08;如新增、删除和更新&#xff09;时有不同的实现方式和优化手段。本文将对比 Vue、React 和 Svelte 在数组渲染方面的特点&#xff0c;并讨论其优缺点&#xff0c;特别是与直接…

【C++】STL——priority_queue优先级队列

目录 前言priority_queue的使用简单使用在OJ中的使用 priority_queue的模拟实现基本功能仿函数在这里插入图片描述 前言 上一节我们说了stack和queue这两种容器适配器&#xff0c;而priority_queue&#xff08;优先级队列&#xff09;同样也是属于容器适配器&#xff0c;它会优…

使用Python在Jupyter Notebook中显示Markdown文本

使用Python在Jupyter Notebook中显示Markdown文本 引言1. 导入必要的模块2. 定义一个函数来显示Markdown文本3. 使用print_md函数显示Markdown文本4. 总结 引言 作为一名Python初级程序员&#xff0c;你可能已经熟悉了Jupyter Notebook这个强大的工具。Jupyter Notebook不仅支…