10分钟了解nextTick,并实现简易版本的nextTick
在 Vue.js 中,有一个特殊的方法 nextTick,它在 DOM 更新后执行一段代码,起到等待 DOM 绘制完成的作用。本文会详细介绍 nextTick 的原理和使用方法,并实现一个简易版的 nextTick,加深对它的理解。
一. 什么是 nextTick
简单的说,nextTick 方法是在 Vue.js 中常见的一种异步更新 DOM 的机制。它的原理是利用 JavaScript 的事件循环机制以及浏览器的渲染流程来实现延迟执行 DOM 更新操作。
它的出现主要是为了解决 Vue 的异步更新导致的 DOM 更新后的操作问题。
在 Vue 中,数据的变化会触发重新渲染 DOM,但实际上,Vue 的数据更新是异步的。也就是说,当我们修改了 Vue 实例的数据后,并不会立即进行 DOM 更新,而是在下一个事件循环中才会进行。
这个异步更新机制的设计是为了优化性能。Vue 会对进行多次数据变化进行合并,然后在下一个事件循环中进行一次性的 DOM 更新,从而减少不必要的 DOM 操作,提高性能。
然而,由于异步更新的机制,有时候可能在修改数据后需要立即执行一些 DOM 操作,例如获取到更新后的 DOM 元素、更新后的样式计算、触发一些特定事件等。这时候就需要使用 nextTick 方法了。
nextTick 方法是 Vue 提供的一个实用工具,它能够将回调函数延迟到下一个 DOM 更新循环之后执行。也就是说,通过 nextTick 方法,我们可以确保在 DOM 更新完成后执行某些操作。
使用 nextTick 方法经常用来解决以下问题:
- 获取更新后的 DOM 元素
- 更新后的样式计算
- 触发一些特定事件
综上所述,nextTick 的出现解决了 Vue 的异步更新机制导致的 DOM 更新后的操作问题,使我们能够在正确的时机执行对应的操作,提高开发效率和灵活性。
二. 实现原理
具体而言,当我们在代码中使用 nextTick 方法时,框架会将待更新的 DOM 操作推入一个队列中,然后在当前 JavaScript 任务执行完成之后,利用宏任务或微任务(具体取决于框架和浏览器实现)的机制进行执行,以确保代码逻辑执行完成后再去操作 DOM。
这样的设计能够确保在当前 JavaScript 运行环境中的任何同步操作完成之后才进行 DOM 的更新,以避免因为 DOM 更新带来的重排或重绘可能导致的性能问题。同时,通过使用异步更新机制,还能够更好地管理大量 DOM 更新的情况,优化渲染性能。
需要注意的是,虽然 nextTick 方法通常被封装在框架中使用,但在一些现代浏览器中也可以直接使用原生的 Promise 或 MutationObserver 等来实现类似的异步更新效果。具体实现方式可能会根据不同的框架和浏览器而有所不同。
nextTick 方法会在下一次 DOM 更新循环结束后执行一个回调函数。这样我们就能确保在操作 DOM 元素之前,DOM 已经更新完成。它通过一些异步的技术来实现,确保回调函数被添加到队列中,并在下一个 tick 执行。
三. 使用场景
下面是我们在日常开发中,几个使用 nextTick 方法的应用场景:
1. 操作更新后的 DOM
当需要对更新后的 DOM 进行操作时,在使用 Vue.js 或其他类似框架的情况下,可以将 DOM 操作代码包裹在 nextTick 的回调函数中。这样可以确保 DOM 更新已经完成,并且在下一个 「DOM 更新循环」 中执行操作,避免出现操作未生效的问题。
<template><div><p>{{ message }}</p><button @click="updateMessage">更新消息</button></div>
</template><script>export default {data() {return {message: "原始消息",};},methods: {updateMessage() {this.message = "更新后的消息";this.$nextTick(() => {// 操作更新后的 DOMconst messageElement = document.querySelector("p");// 输出:更新后的消息console.log(messageElement.textContent);});},},};
</script>
注意:以上的代码仅用于示例作用,在Vue中不建议直接操作 DOM 元素
当点击 「更新消息」 按钮时,updateMessage 方法会将 message 的值更新为 「更新后的消息」。在 $nextTick 的回调函数中,我们可以通过选择器获取到更新后的 DOM 元素,并进行相应的操作。
2. 异步更新后的操作
当需要在 DOM 更新后执行一些异步操作时,如在表单数据更新后提交表单、在列表数据更新后进行滚动定位等,可以在 nextTick 回调函数中触发相应的异步操作。这样可以保证在下一个事件循环周期中执行操作,以确保更新已经完成。
<template><div><ul><li v-for="item in items" :key="item.id">{{ item.name }}</li></ul><button @click="updateItems">更新列表</button></div>
</template><script>export default {data() {return {items: [{ id: 1, name: "Item 1" },{ id: 2, name: "Item 2" },{ id: 3, name: "Item 3" },],};},methods: {updateItems() {// 异步更新数据setTimeout(() => {this.items.push({ id: 4, name: "Item 4" });this.$nextTick(() => {// 在更新后的 DOM 中进行滚动定位const lastItem = document.querySelector("li:last-child");lastItem.scrollIntoView({ behavior: "smooth" });});}, 1000);},},};
</script>
当点击 「更新列表」 按钮时,updateItems 方法会通过异步操作向 items 数组中添加新的项。在 $nextTick 的回调函数中,我们可以在 DOM 更新后将最后一个项滚动到可视区域。
通过以上两个示例,我们可以看到 nextTick 的应用场景,其中关键就是将需要在 DOM 更新后进行操作的代码放在 nextTick 的回调函数中,以确保更新已经完成。同时,可以结合异步操作来优化用户体验或性能。
四. 如何实现一个简易版的 nextTick
当我们在 Vue 中自己实现一个类似 $nextTick 的方法时,可以考虑使用 JavaScript 的 Promise 和 MutationObserver 来模拟其行为,下面我们具体来看一下吧:
// 自定义的 $nextTick 方法
Vue.prototype.$myNextTick = function () {return new Promise((resolve) => {if (typeof MutationObserver !== "undefined") {// 使用 MutationObserver 监听 DOM 变化let observer = new MutationObserver(resolve);let textNode = document.createTextNode("1");observer.observe(textNode, {characterData: true,});textNode.textContent = "2";} else {// fallback 方案,使用 setTimeout 模拟异步setTimeout(resolve, 0);}});
};
- 首先,我们在
Vue.prototype上添加了一个名为$myNextTick的方法。通过在prototype对象上添加该方法,我们可以在 Vue 的实例上使用$myNextTick方法。 Vue.prototype.$myNextTick方法内部返回了一个Promise对象。通过返回Promise对象,我们可以使用.then或async/await语法来处理Promise的解析。- 在方法的 Promise 回调函数中,我们首先检查当前环境是否支持
MutationObserver。MutationObserver是一个用于异步监听 DOM 变化的 API。 - 如果当前环境支持
MutationObserver,我们会创建一个MutationObserver实例,并将它的回调函数设置为resolve。我们创建了一个文本节点,并将其添加到 DOM 中,然后通过修改文本节点的内容来触发 DOM 变化。当 DOM 变化时,MutationObserver的回调函数resolve就会被调用。 - 如果当前环境不支持
MutationObserver,我们将使用setTimeout来模拟异步操作。我们使用一个 0 毫秒的延迟来确保resolve在下一个事件循环中执行,模拟了异步的效果。
完成了简易版$nextTick后,下面看一下如何使用 $myNextTick 吧:
// 示例组件
new Vue({el: "#app",data() {return {message: "Hello, Vue!",};},methods: {updateMessage() {this.message = "Updated Message";this.$myNextTick().then(() => {console.log("DOM 已更新");// 在 DOM 更新后进行其他操作});},},
});
在这个示例中,当点击按钮时,会调用 updateMessage 方法,该方法会将 message 的值更新为 「Updated Message」。然后通过 $myNextTick 方法返回的 Promise 对象来确保在 DOM 更新之进行其他操作。
通过这样的实现,我们可以在 Vue 组件中使用 $myNextTick 方法来执行在 DOM 更新后的操作,类似于 Vue 原生的 $nextTick 方法的效果。
注意,这只是一种模拟实现,其目的为了加深对 Vue 版 $nextTick 的理解,代码可能无法完全复制 Vue 原生的 $nextTick 的行为。因此,在实际开发中,建议还是使用 Vue 提供的内置 $nextTick 方法来保证更准确和可靠的 DOM 更新后操作。
五. 注意事项
在使用 nextTick 方法时,需要注意以下几点:
nextTick方法是一个实例方法,在 Vue 组件中可以直接使用,但在其他地方需要通过 Vue 实例来调用,例如:this.$nextTick()nextTick方法是异步的,回调函数会在下一次 DOM 更新循环结束后执行,因此并不是立即执行的。nextTick方法支持使用 Promise 或返回 Promise 的函数来进行链式调用。
相关文章:
10分钟了解nextTick,并实现简易版本的nextTick
在 Vue.js 中,有一个特殊的方法 nextTick,它在 DOM 更新后执行一段代码,起到等待 DOM 绘制完成的作用。本文会详细介绍 nextTick 的原理和使用方法,并实现一个简易版的 nextTick,加深对它的理解。 一. 什么是 nextTic…...
oracle表空间对象迁移到其他表空间
oracle数据库的磁盘空间满了,除了简单粗暴的增加磁盘空间外,还可以缩小表空间的datafile,因为正常业务运行中,表数据的删除和增加,会造成表空间里面里面有很多空的地方。方案有很多种,我这里简单介绍一下&a…...
<stdlib.h>头文件: C 语言常用标准库函数详解
文章目录 引言1. <stdlib.h> 概览1.1 头文件包含 2. 内存管理函数2.1 malloc 函数2.2 calloc 函数2.3 realloc 函数2.4 free 函数 3. 随机数生成函数3.1 rand 函数3.2 srand 函数 4. 字符串转换函数4.1 atoi 函数4.2 atof 函数4.3 itoa 函数4.4 ltoa 函数4.5 ultoa函数 5…...
Qt前端技术:3.QSS字体样式
small-caps就是让这个文本中的小写字母用大写的形式写出来并且在用大写的形式表达出来后他本身的大小会变小 有绝对尺寸和相对尺寸的区别 绝对尺寸一般是cm,英寸之类的 相对尺寸如px之类的是由显示器的屏幕分辨率来决定的 如windows用户分辨率一般是96像素点每英…...
阿里面试官:面试了一个能力相当不错的候选人,但背调时,他前同事和领导都说他人品很差,纠结该不该要他?...
* 你好,我是前端队长,在职场,玩副业,文末有福利! 在职场中,背调是个躲不开的事情。不管是各行各业背调可能都存在,只是形式不同而已。而且现在大环境不好,可能对个人的要求还更高一些。 背调的主…...
如何设计树形结构
作者简介:大家好,我是smart哥,前中兴通讯、美团架构师,现某互联网公司CTO 联系qq:184480602,加我进群,大家一起学习,一起进步,一起对抗互联网寒冬 前置知识:前…...
限量25台,川崎亮相Ninja ZX-10RR冬季限量款
最近川崎发布了自家ZX-10RR的超级限量版,官方称之为冬季测试版,之前也有一些车型推出过冬季测试版,通常是在年底推出,因为这个时候北半球都是非常寒冷的冬天。 不过这台ZX-10RR冬季测试版,并不仅仅只是限量那么简单&am…...
【QT八股文】系列之篇章1 | QT的基础知识及事件/机制
【QT八股文】系列之篇章1 | QT的基础知识及事件/机制 前言0. 基础Qt/PyQt5介绍/关联Qt的优缺点(为什么要用qt来做界面)Qt 的核心机制请简要介绍一下Qt中的主窗口(MainWindow)类,它有哪些重要的函数和成员变量ÿ…...
SpringBoot 3 集成Hive 3
前提条件: 运行环境:Hadoop 3.* Hive 3.* MySQL 8 ,如果还未安装相关环境,请参考:Hive 一文读懂 Centos7 安装Hadoop3 单机版本(伪分布式版本) SpringBoot 2 集成Hive 3 pom.xml <?xml ver…...
STL中优先队列的模拟实现与仿函数的介绍
文章目录 仿函数优先队列的模拟实现 仿函数 上回我们说到,优先队列的实现需要用到仿函数的特性 让我们再回到这里 这里我们发现他传入的用于比较的东西竟然是一个类模板,而不是我们所见到的函数 我们可以先创建一个类,用于比较大小 struc…...
LeetCode刷题--- 目标和
个人主页:元清加油_【C】,【C语言】,【数据结构与算法】-CSDN博客 个人专栏 力扣递归算法题 http://t.csdnimg.cn/yUl2I 【C】 http://t.csdnimg.cn/6AbpV 数据结构与算法 http://t.csdnimg.cn/hKh2l 前言:这个专栏主要讲述递归递归、搜…...
【.NET Core】反射(Reflection)详解(二)
【.NET Core】反射(Reflection)详解(二) 文章目录 【.NET Core】反射(Reflection)详解(二)一、概述二、Type类2.1 Type对象表示哪些类型2.2 获取Type及其关联对象类型的方式2.3 Type…...
【错误记录/js】保存octet-stream为文件后数据错乱
目录 说在前面场景解决方式其他 说在前面 后端:go、gin浏览器:Microsoft Edge 120.0.2210.77 (正式版本) (64 位) 场景 前端通过点击按钮来下载一些文件,但是文件内容是一些非文件形式存储的二进制数据。 后端代码 r : gin.Default()r.Stat…...
sql_lab之sqli中的post注入
Post注入 用burpsuit抓包去做 Post第一关:(gxa5) 1.判断是否存在注入 username1or 11 #&password123&submit%E7%99%BB%E5%BD%95 有回显 username1or 12 #&password123&submit%E7%99%BB%E5%BD%95 没有回显 则证明存在sq…...
智能优化算法应用:基于白冠鸡算法3D无线传感器网络(WSN)覆盖优化 - 附代码
智能优化算法应用:基于白冠鸡算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用:基于白冠鸡算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.白冠鸡算法4.实验参数设定5.算法结果6.参考文…...
DETR++: Taming Your Multi-Scale Detection Transformer论文解读
文章目录 前言一、摘要二、引言三、相关研究四、模型方法1、Removing the Encoder方法2、Multi-Head方法3、Shifted Windows方法4、Bi-directional Feature Pyramid方法5、DETR方法 五、实验结果总结 前言 今天查看了一篇DETR论文,本想网络上找博客大概浏览一下&am…...
高级数据结构 <二叉搜索树>
本文已收录至《数据结构(C/C语言)》专栏! 作者:ARMCSKGT 目录 前言正文二叉搜索树的概念二叉搜索树的基本功能实现二叉搜索树的基本框架插入节点删除节点查找函数中序遍历函数析构函数和销毁函数(后序遍历销毁)拷贝构造和赋值重载(前序遍历创建)其他函数…...
蚂蚁集团5大开源项目获开放原子 “2023快速成长开源项目”
12月16日,在开放原子开源基金会主办的“2023开放原子开发者大会”上,蚂蚁集团主导开源的图数据库TuGraph、时序数据库CeresDB、隐私计算框架隐语SecretFlow、前端框架OpenSumi、数据域大模型开源框架DB-GPT入选“2023快速成长开源项目”。 (图…...
SpringBoot+JaywayJsonPath实现Json数据的DSL(按照指定节点表达式解析json获取指定数据)
场景 若依前后端分离版手把手教你本地搭建环境并运行项目: 若依前后端分离版手把手教你本地搭建环境并运行项目_前后端分离项目本地运行-CSDN博客 在上面搭建SpringBoot项目的基础上,并且在项目中引入fastjson、hutool等所需依赖后。 Jayway JsonPat…...
气压计LPS28DFW开发(2)----水压检测
气压计LPS28DFW开发.2--水压检测 概述视频教学样品申请完整代码下载水压计算设置速率和分辨率轮询读取数据测试结果 概述 本文将介绍如何使用 LPS28DFW 传感器来读取的压强数据,来估算水下深度,可以利用液体静压的原理。 最近在弄ST和瑞萨RA的课程&…...
docker详细操作--未完待续
docker介绍 docker官网: Docker:加速容器应用程序开发 harbor官网:Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台,用于将应用程序及其依赖项(如库、运行时环…...
Unsafe Fileupload篇补充-木马的详细教程与木马分享(中国蚁剑方式)
在之前的皮卡丘靶场第九期Unsafe Fileupload篇中我们学习了木马的原理并且学了一个简单的木马文件 本期内容是为了更好的为大家解释木马(服务器方面的)的原理,连接,以及各种木马及连接工具的分享 文件木马:https://w…...
HashMap中的put方法执行流程(流程图)
1 put操作整体流程 HashMap 的 put 操作是其最核心的功能之一。在 JDK 1.8 及以后版本中,其主要逻辑封装在 putVal 这个内部方法中。整个过程大致如下: 初始判断与哈希计算: 首先,putVal 方法会检查当前的 table(也就…...
基于PHP的连锁酒店管理系统
有需要请加文章底部Q哦 可远程调试 基于PHP的连锁酒店管理系统 一 介绍 连锁酒店管理系统基于原生PHP开发,数据库mysql,前端bootstrap。系统角色分为用户和管理员。 技术栈 phpmysqlbootstrapphpstudyvscode 二 功能 用户 1 注册/登录/注销 2 个人中…...
BLEU评分:机器翻译质量评估的黄金标准
BLEU评分:机器翻译质量评估的黄金标准 1. 引言 在自然语言处理(NLP)领域,衡量一个机器翻译模型的性能至关重要。BLEU (Bilingual Evaluation Understudy) 作为一种自动化评估指标,自2002年由IBM的Kishore Papineni等人提出以来,…...
Chromium 136 编译指南 Windows篇:depot_tools 配置与源码获取(二)
引言 工欲善其事,必先利其器。在完成了 Visual Studio 2022 和 Windows SDK 的安装后,我们即将接触到 Chromium 开发生态中最核心的工具——depot_tools。这个由 Google 精心打造的工具集,就像是连接开发者与 Chromium 庞大代码库的智能桥梁…...
Linux系统部署KES
1、安装准备 1.版本说明V008R006C009B0014 V008:是version产品的大版本。 R006:是release产品特性版本。 C009:是通用版 B0014:是build开发过程中的构建版本2.硬件要求 #安全版和企业版 内存:1GB 以上 硬盘…...
LLaMA-Factory 微调 Qwen2-VL 进行人脸情感识别(二)
在上一篇文章中,我们详细介绍了如何使用LLaMA-Factory框架对Qwen2-VL大模型进行微调,以实现人脸情感识别的功能。本篇文章将聚焦于微调完成后,如何调用这个模型进行人脸情感识别的具体代码实现,包括详细的步骤和注释。 模型调用步骤 环境准备:确保安装了必要的Python库。…...
Axure 下拉框联动
实现选省、选完省之后选对应省份下的市区...
Linux安全加固:从攻防视角构建系统免疫
Linux安全加固:从攻防视角构建系统免疫 构建坚不可摧的数字堡垒 引言:攻防对抗的新纪元 在日益复杂的网络威胁环境中,Linux系统安全已从被动防御转向主动免疫。2023年全球网络安全报告显示,高级持续性威胁(APT)攻击同比增长65%,平均入侵停留时间缩短至48小时。本章将从…...
