Vue 中 $nextTick 的作用是什么?

news2024/12/23 18:38:41

目录

一、NextTick是什么

        为什么要有nexttick

二、使用场景

三、实现原理


一、NextTick是什么

官方对其的定义

在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM

什么意思呢?

我们可以理解成,Vue 在更新 DOM 时是异步执行的。当数据发生变化,Vue将开启一个异步更新队列,视图需要等队列中所有数据变化完成之后,再统一进行更新

举例一下

Html结构

<div id="app"> {{ message }} </div>

构建一个vue实例

const vm = new Vue({
  el: '#app',
  data: {
    message: '原始值'
  }
})

修改message

this.message = '修改后的值1'
this.message = '修改后的值2'
this.message = '修改后的值3'

这时候想获取页面最新的DOM节点,却发现获取到的是旧值

console.log(vm.$el.textContent) // 原始值

这是因为message数据在发现变化的时候,vue并不会立刻去更新Dom,而是将修改数据的操作放在了一个异步操作队列中

如果我们一直修改相同数据,异步操作队列还会进行去重

等待同一事件循环中的所有数据变化完成之后,会将队列中的事件拿来进行处理,进行DOM的更新

为什么要有nexttick

举个例子

{{num}}
for(let i=0; i<100000; i++){
    num = i
}

如果没有 nextTick 更新机制,那么 num 每次更新值都会触发视图更新(上面这段代码也就是会更新10万次视图),有了nextTick机制,只需要更新一次,所以nextTick本质是一种优化策略

二、使用场景

如果想要在修改数据后立刻得到更新后的DOM结构,可以使用Vue.nextTick()

第一个参数为:回调函数(可以获取最近的DOM结构)

第二个参数为:执行函数上下文

// 修改数据
vm.message = '修改后的值'
// DOM 还没有更新
console.log(vm.$el.textContent) // 原始的值
Vue.nextTick(function () {
  // DOM 更新了
  console.log(vm.$el.textContent) // 修改后的值
})

组件内使用 vm.$nextTick() 实例方法只需要通过this.$nextTick(),并且回调函数中的 this 将自动绑定到当前的 Vue 实例上

this.message = '修改后的值'
console.log(this.$el.textContent) // => '原始的值'
this.$nextTick(function () {
    console.log(this.$el.textContent) // => '修改后的值'
})
$nextTick() 会返回一个 Promise 对象,可以是用async/await完成相同作用的事情

this.message = '修改后的值'
console.log(this.$el.textContent) // => '原始的值'
await this.$nextTick()
console.log(this.$el.textContent) // => '修改后的值'

三、实现原理

源码位置:/src/core/util/next-tick.js

callbacks也就是异步操作队列

callbacks新增回调函数后又执行了timerFunc函数,pending是用来标识同一个时间只能执行一次

export function nextTick(cb?: Function, ctx?: Object) {
  let _resolve;

  // cb 回调函数会经统一处理压入 callbacks 数组
  callbacks.push(() => {
    if (cb) {
      // 给 cb 回调函数执行加上了 try-catch 错误处理
      try {
        cb.call(ctx);
      } catch (e) {
        handleError(e, ctx, 'nextTick');
      }
    } else if (_resolve) {
      _resolve(ctx);
    }
  });

  // 执行异步延迟函数 timerFunc
  if (!pending) {
    pending = true;
    timerFunc();
  }

  // 当 nextTick 没有传入函数参数的时候,返回一个 Promise 化的调用
  if (!cb && typeof Promise !== 'undefined') {
    return new Promise(resolve => {
      _resolve = resolve;
    });
  }
}

timerFunc函数定义,这里是根据当前环境支持什么方法则确定调用哪个,分别有:

Promise.thenMutationObserversetImmediatesetTimeout

通过上面任意一种方法,进行降级操作

export let isUsingMicroTask = false
if (typeof Promise !== 'undefined' && isNative(Promise)) {
  //判断1:是否原生支持Promise
  const p = Promise.resolve()
  timerFunc = () => {
    p.then(flushCallbacks)
    if (isIOS) setTimeout(noop)
  }
  isUsingMicroTask = true
} else if (!isIE && typeof MutationObserver !== 'undefined' && (
  isNative(MutationObserver) ||
  MutationObserver.toString() === '[object MutationObserverConstructor]'
)) {
  //判断2:是否原生支持MutationObserver
  let counter = 1
  const observer = new MutationObserver(flushCallbacks)
  const textNode = document.createTextNode(String(counter))
  observer.observe(textNode, {
    characterData: true
  })
  timerFunc = () => {
    counter = (counter + 1) % 2
    textNode.data = String(counter)
  }
  isUsingMicroTask = true
} else if (typeof setImmediate !== 'undefined' && isNative(setImmediate)) {
  //判断3:是否原生支持setImmediate
  timerFunc = () => {
    setImmediate(flushCallbacks)
  }
} else {
  //判断4:上面都不行,直接用setTimeout
  timerFunc = () => {
    setTimeout(flushCallbacks, 0)
  }
}
无论是微任务还是宏任务,都会放到flushCallbacks使用

这里将callbacks里面的函数复制一份,同时callbacks置空

依次执行callbacks里面的函数

function flushCallbacks () {
  pending = false
  const copies = callbacks.slice(0)
  callbacks.length = 0
  for (let i = 0; i < copies.length; i++) {
    copies[i]()
  }
}

小结:

  1. 把回调函数放入callbacks等待执行
  2. 将执行函数放到微任务或者宏任务中
  3. 事件循环到了微任务或者宏任务,执行函数依次执行callbacks中的回调

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

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

相关文章

一路串联电机的绕制原理

这里要说明的一点是 对于一路串联的电机&#xff0c;无论是一把线圈还是两把线圈&#xff0c;出来的都是只有两个线头&#xff0c;可看做一个整体来对待&#xff01; 绕制具体原理 同心式线圈绕制 前面说的都是等距式的 线圈绕制&#xff0c;下面我们讲解一下同心式的绕制办法…

Android studio 打开Device Mirroring方便调试

巧合下发现一个很好用的工具&#xff0c;在平时调试真机的时候在每次run app后都要低头找找手机看看效果。但是&#xff0c;用了AS上的Device Mirroring&#xff0c;你会发现根本不需要再低头点手机&#xff0c;调试方便一万倍啊。 话不多说&#xff0c;上图。直接就可以在电脑…

ogv转mp4怎么转?只需3个步骤~

OGV&#xff08;Ogg Video&#xff09;是一种开源的视频文件格式&#xff0c;起源于对数字媒体领域的开放标准的需求。作为Ogg多媒体容器的一部分&#xff0c;OGV的设计初衷是提供一种自由、高质量的视频编码方案&#xff0c;以满足多样化的应用需求。 支持打开MP4文件格式的软…

基于SpringBoot的高校推荐系统

项目介绍 当前&#xff0c;随着高等教育的不断普及&#xff0c;越来越多的学生选择考研究生来提高自身的学术水平和竞争力。然而&#xff0c;考研生在选择报考院校和专业时面临着众多的选择和信息不对称的问题。为了解决这些问题&#xff0c;一些网站和APP已经推出了相关的院校…

2024年数维杯数学建模ABC题思路分析

文章目录 1 赛题思路2 比赛日期和时间3 竞赛信息4 建模常见问题类型4.1 分类问题4.2 优化问题4.3 预测问题4.4 评价问题 5 建模资料 1 赛题思路 (赛题出来以后第一时间在CSDN分享) https://blog.csdn.net/dc_sinor?typeblog 2 比赛日期和时间 报名截止时间&#xff1a;2024…

Find My资讯|苹果设备在修复期间可以保持启用“Find My“功能

iOS 17.5 中有一项名为"维修状态"的新功能&#xff0c;可让送修的设备保持启用"查找我的"&#xff08;Find My&#xff09;功能。此前&#xff0c;用户在送修设备时必须禁用跟踪设备位置的"查找我的"功能&#xff0c;但iOS 17.5发布后&#xff0…

YOLOv8原理解析[目标检测理论篇]

接下来是我最想要分享的内容&#xff0c;梳理了YOLOv8预测的整个流程&#xff0c;以及训练的整个流程。 关于YOLOv8的主干网络在YOLOv8网络结构介绍-CSDN博客介绍了&#xff0c;为了更好地介绍本章内容&#xff0c;还是把YOLOv8网络结构图放在这里&#xff0c;方便查看。 1.YOL…

C++奇迹之旅:string类对象的容量操作

文章目录 &#x1f4dd; string类的常用接口&#x1f309; string类对象的容量操作&#x1f320;size&#x1f320;length&#x1f320;capacity&#x1f320;clear&#x1f320;empty&#x1f320;reserve&#x1f309;resize &#x1f6a9;总结 &#x1f4dd; string类的常用…

通义千问免费新功能:EMO,让照片和视频“活”起来

&#x1f9d9;‍♂️ 诸位好&#xff0c;吾乃斜杠君&#xff0c;编程界之翘楚&#xff0c;代码之大师。算法如流水&#xff0c;逻辑如棋局。 &#x1f4dc; 吾之笔记&#xff0c;内含诸般技术之秘诀。吾欲以此笔记&#xff0c;传授编程之道&#xff0c;助汝解技术难题。 &#…

编写burp插件实现数据包自定义修改

背景 安全测试工作中经常遇到各种加密加签或者添加了其它安全措施的数据包。以加密为例&#xff0c;为了测试正常进行&#xff0c;我们需要解密后修改数据包再进行加密还原&#xff0c;手工的话很是繁琐且没必要&#xff0c;所以我们需要一个工具帮我们自动化的实现。由于我们…

盘点一下近年来常用的电脑监控软件

企业电脑监控软件通常用于监视员工在工作时间内的电脑使用情况&#xff0c;以确保他们的工作效率和安全性。以下是几种常见的企业电脑监控软件&#xff1a; 1、Ping32 Ping32是一款集成多功能的企业级电脑监控软件&#xff0c;包括员工上网行为管理、文件外发审计、屏幕活动监…

Stable Diffusion Ai绘画模型推荐:二次元Coriander_Mix v1大模型推荐

负tag嵌入式:EasyNegative,badhandv4 此模型经测试是写实偏3D的效果 画质灰暗的话请加&#xff1a;VAE840000 或者负tag&#xff1a;(watermark:2),(blurry:2),fat,paintings,sketches,(worst quality:2),(low quality:2),(normal quality:2),((monochrome)), ((grayscale))…

Redis 源码安装(CentOS 单机)

序言 本文给大家介绍如何在 CentOS 上&#xff0c;通过 Redis 源码单机部署 Redis 服务。 一、部署流程 通过官网下载源码 # 下载源码 wget https://download.redis.io/redis-stable.tar.gz# 解压源码包 tar -xzvf redis-stable.tar.gz在 linux 中执行以下命令&#xff0c;安…

工业级路由器的穿透力是不是更强(原创科普)

今天我想和大家聊聊工业级路由器的一个重要特性——穿透力。作为一名从事工业网络通信的工程师,我发现很多用户在选择工业级路由器时,都会问到一个问题:"工业级路由器的穿透力是不是更强?"下面就让我来为大家解答这个疑问。当然如果有通信产品需要也可以关注星创易联…

修图新风尚:AI技术赋能,Remini引领修图新纪元,从Remini到未来,AI修图如何改变我们的视觉世界?

最近一款名为Remini的AI修图软件凭借其独特的“丑萌”的黏土风格&#xff0c;迅速在海内外市场走红。 用户只需要上传一张照片&#xff0c;就可以利用AI技术生成对应的黏土滤镜风格的图像。 “黏土AI”风格的图像刷爆了今年的五一假期旅游照片“大赛”&#xff0c;在小红书、…

【京东电商API接口】 | 京东某商品销量数据分析可视化

Python当打之年 当打之年&#xff0c;专注于各领域Python技术&#xff0c;量的积累&#xff0c;质的飞跃。后台回复&#xff1a;【可视化项目源码】可获取可视化系列文章源码和数据 本期将利用Python分析「京东商品数据接口」&#xff0c;希望对大家有所帮助&#xff0c;如有疑…

检测机构的双资质是什么?

CMA和CNAS是两种在检测、校准和认证领域具有权威性的资质。 CMA资质全称为“检验检测机构资质认定”&#xff08;China Inspection Body and Laboratory Mandatory Approval&#xff09;。它是根据《中华人民共和国计量法》等相关法规&#xff0c;由国家认证认可监督管理委员会…

Python 中的 Unit testing 文件写入

在 Python 中进行单元测试时&#xff0c;有时候需要测试文件写入操作。为了模拟文件写入并进行单元测试&#xff0c;你可以使用 Python 的 unittest 模块&#xff0c;并结合 io.StringIO 或 tempfile 模块来模拟文件操作。 1、问题背景 在 Python 中&#xff0c;为 ConfigPars…

Chromium编译指南2024 Windows11篇-GN 工具生成构建文件(六)

前言 在《Chromium编译指南2024&#xff08;五&#xff09;》我们已经获取了 Chromium 的源代码并且同步了相关的第三方依赖。 现在&#xff0c;我们将进一步学习如何使用 GN 工具生成构建文件&#xff0c;为后续的编译工作做好准备。 1. 使用gn工具生成构建文件 再次在Win…