搜索
首页web前端Vue.js带你深入了解下this.$nextTick!
带你深入了解下this.$nextTick!Dec 21, 2022 pm 08:43 PM
vue$nexttick

带你深入了解下this.$nextTick!

都快2023年,你还不会this.$nextTick吗,Vue2都出快10年了,Vue3也已经出了两年多了,没错!说出来就丢脸,我现在才会this.nextTick(实话实说),好的咱先百度一下,哒哒哒....网速飞快地跳到了Vue.js官网文档,突然发现文档中有一言?:

nextTick:在下一次DOM更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的DOM。它有两个参数:第一个参数是回调函数,不传时提供promise调用;第二个参数是执行环境上下文,不传默认是自动绑定到调用它的实例上。【相关推荐:vuejs视频教程web前端开发

我们先看看nextTick究竟是个啥?

console.log(this.$nextTick);
// 控制台打印
if(fn){
  return nextTick(fn, this);
}

我们可以看出nextTick就是一个方法,方法有两个参数:fn和this,fn就是需要传的回调函数,this就是所说的执行环境上下文。那么问题来了,在Vue中是如何实现在下一次DOM更新结束之后才会执行延迟回调的? 我们先看看下面的例子:

<div ref="test1">created:{{message}}</div>
// vue实例
data: {
    message: "Hello World!",
},
created(){
    this.message = &#39;你好,世界!&#39;;
    console.log(this.$refs.test1.innerText);// 报错
    // TypeError: Cannot read properties of undefined (reading &#39;innerText&#39;)
    this.$nextTick(()=>{
         console.log(&#39;test1 nextTick:&#39;,this.$refs.test1.innerText);// 你好,世界!
    });
},

从上面例子中,在created生命周期中操作了DOM,但是我们都知道created生命周期只是初始化了数据,这期间是还没有渲染DOM的,如果我们直接操作DOM是找不到DOM元素的,那么问题来了:为什么放在nextTick中就可以获取到了DOM元素呢? 这不是很明显吗,等到DOM渲染完才调用不就获取到了吗,从而知道了nextTick作用就是用来等下次DOM渲染完才去调用nextTick内的DOM操作代码。那么问题又来了,nextTick究竟做了什么?下面我们一起从源码层面来分别分析Vue2和Vue3版本的nextTick原理是啥。

Vue2版本的nextTick

由于Vue暴露给开发者的是nextTick这个方法,在这个方法中主要做了三件事,回调函数的添加延迟执行回调函数判断当前的nextTick是否传入回调函数。不传的话,是一个Promise,this.$nextTick.then(()=>{}),按Promise处理。

image.png

  • 回调函数添加入callbacks数组,因为可能有多个nextTick函数在当前作用域中。

image.png

  • 判断当前nextTick是否已经标记为pending=true,也就是正在执行,如果不是就执行timerFunc(异步执行函数 用于异步延迟调用 flushCallbacks 函数)。timerFunc的执行,判断当前环境是否支持promise、MutationObserver、setImmediate、setTimeout,优先级高低从前到后,分四种情况:
  • 优先使用Promise,如果当前环境支持promise,nextTick默认优先使用promise去执行延迟回调函数,timerFunc执行的是Promise,promise是es6下的语法,如果当前环境只支持es6以语法下的,只能考虑后面支持情况了。

image.png

  • 支持MutationObserver,HTML5的api,中文意思是:修改的监听,MutationObserver用来监听DOM的变动,比如节点的增减、属性的变动、文本内容的修改等都会触发MutationObserver事件。注意地,与事件不同,事件是同步触发,DOM的变动会立即触发事件,而MutationObserver事件是异步触发,DOM不会立即触发,需要等当前所有DOM操作完毕才会触发。

MutationObserver有7个属性:childList(true,监听子节点的变动)、attributes(true,监听属性的变动)、characterData(true,监听节点内容或节点文本的变动)、subtree(是否应用于该节点的所有后代节点)、attributeOldValue(观察attributes变动时,是否需要记录变动前的属性值)、characterDataOldValue(观察characterData变动时,是否需要记录变动前的值)、attributeFilter(数组,表示需要观察的特定属性(比如[‘class’,‘src’])。

为什么需要创建一个文本节点?因为在这里操作DOM保证浏览器页面是最新DOM渲染的,虽然看来好像是没什么作用,但这是保证拿到的DOM是最新的。

image.png

  • 支持setImmediatesetTimeout,setImmediate即时计时器立即执行工作,它是在事件轮询之后执行,为了防止轮询阻塞,每次只会调用一个。setTimeout按照一定时间后执行回调函数。

image.png

好了好了,到了现在,我们都知道nextTick做了什么吧,但是我们有没有想过这样的一个问题:既然都是异步回调执行等待DOM更新后才去调用操作DOM的代码,那么这个机制又是什么原理?这就是JS的执行机制有关了,涉及宏任务与微任务的知识,我们先来看看这样的一道题:

console.log(&#39;同步代码1&#39;);
setTimeout(function () {
    console.log("setTimeout");
}, 0);
new Promise((resolve) => {
    console.log(&#39;同步代码2&#39;)
    resolve()
}).then(() => {
    console.log(&#39;promise.then&#39;)
})
console.log(&#39;同步代码3&#39;);

我们可能会问上面的输出是个啥,首先js是单线程,所以在js程序运行中只有一个执行栈,实现不了多线程,所以就需要任务均衡分配,通俗的讲,按任务急优先处理原则,js中分为同步任务和异步任务,异步任务又分为宏任务和微任务,同步任务先入栈,程序会先把执行栈中的所有同步任务执行完,再去判断是否有异步任务,而异步任务中微任务的优先级高于宏任务。如果当前执行栈为空,而微任务队列不为空,就先执行微任务,等把所有微任务执行完,最后才会考虑宏任务。而上面代码中Promise是属于微任务,而setTimeout是宏任务,所以上面的输出为:

// 同步代码1
// 同步代码2
// 同步代码3
// promise.then 
// setTimeout

使用Vue2的nextTick

  • 传入回调函数参数使用:

    this.$nextTick(()=>{
      // ...操作DOM的代码
    })
  • 不传入回调函数参数使用:

    // 方式一
    this.$nextTick().then(()=>{
      // ...操作DOM的代码
    })
    
    // 方式二
    await this.$nextTick();
    // 后写操作DOM的代码

Vue3版本的nextTick

Vue3版本就没有Vue2版本的那么多环境支持,nextTick封装成了一个Promise异步回调函数执行。

// Vue3.2.45
// core-main\core-main\packages\runtime-core\src
export function nextTick<T = void>(
  this: T,
  fn?: (this: T) => void
): Promise<void> {
  const p = currentFlushPromise || resolvedPromise
  return fn ? p.then(this ? fn.bind(this) : fn) : p
}

使用Vue3的nextTick

  • 传入回调函数使用

    import { nextTick } from &#39;vue&#39; // 引入
    setup () {    
    nextTick(()=>{
       // ...操作DOM的代码
    })
  • 不传入回调函数的使用

    import { nextTick } from &#39;vue&#39; // 引入
    setup () {    
        // 方式一
        nextTick().then(()=>{
          // ...操作DOM的代码
        })
    
        // 方式二
        await nextTick();
        // 后写操作DOM的代码
    }

总结

  • nextTick可以通俗的当作一个Promise,所以nextTick属于微任务。
  • nextTick在页面更新数据后,DOM更新,可以通俗理解为,nextTick就是用来支持操作DOM的代码及时更新渲染页面。也就是在数据变化后要执行的某个操作,而这个操作需要使用随数据改变而改变的DOM结构的时候,这个操作都应该放进Vue.nextTick()的回调函数中。
  • 在Vue生命周期的created()钩子函数进行的DOM操作一定要放在Vue.nextTick()的回调函数中。

(学习视频分享:vuejs入门教程编程基础视频

以上是带你深入了解下this.$nextTick!的详细内容。更多信息请关注PHP中文网其他相关文章!

声明
本文转载于:掘金社区。如有侵权,请联系admin@php.cn删除
Vue常见面试题汇总(附答案解析)Vue常见面试题汇总(附答案解析)Apr 08, 2021 pm 07:54 PM

本篇文章给大家分享一些Vue面试题(附答案解析)。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。

5 款适合国内使用的 Vue 移动端 UI 组件库5 款适合国内使用的 Vue 移动端 UI 组件库May 05, 2022 pm 09:11 PM

本篇文章给大家分享5 款适合国内使用的 Vue 移动端 UI 组件库,希望对大家有所帮助!

手把手带你利用vue3.x绘制流程图手把手带你利用vue3.x绘制流程图Jun 08, 2022 am 11:57 AM

利用vue3.x怎么绘制流程图?下面本篇文章给大家分享基于 vue3.x 的流程图绘制方法,希望对大家有所帮助!

如何覆盖组件库样式?React和Vue项目的解决方法浅析如何覆盖组件库样式?React和Vue项目的解决方法浅析May 16, 2022 am 11:15 AM

如何覆盖组件库样式?下面本篇文章给大家介绍一下React和Vue项目中优雅地覆盖组件库样式的方法,希望对大家有所帮助!

聊聊vue指令中的修饰符,常用事件修饰符总结聊聊vue指令中的修饰符,常用事件修饰符总结May 09, 2022 am 11:07 AM

本篇文章带大家聊聊vue指令中的修饰符,对比一下vue中的指令修饰符和dom事件中的event对象,介绍一下常用的事件修饰符,希望对大家有所帮助!

通过9个Vue3 组件库,看看聊前端的流行趋势!通过9个Vue3 组件库,看看聊前端的流行趋势!May 07, 2022 am 11:31 AM

本篇文章给大家分享9个开源的 Vue3 组件库,通过它们聊聊发现的前端的流行趋势,希望对大家有所帮助!

react与vue的虚拟dom有什么区别react与vue的虚拟dom有什么区别Apr 22, 2022 am 11:11 AM

react与vue的虚拟dom没有区别;react和vue的虚拟dom都是用js对象来模拟真实DOM,用虚拟DOM的diff来最小化更新真实DOM,可以减小不必要的性能损耗,按颗粒度分为不同的类型比较同层级dom节点,进行增、删、移的操作。

VSCode插件分享:一个实时预览Vue/React组件的插件VSCode插件分享:一个实时预览Vue/React组件的插件Mar 17, 2022 pm 08:07 PM

在VSCode中开发Vue/React组件时,怎么实时预览组件?本篇文章就给大家分享一个VSCode 中实时预览Vue/React组件的插件,希望对大家有所帮助!

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
2 周前By尊渡假赌尊渡假赌尊渡假赌
仓库:如何复兴队友
4 周前By尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island冒险:如何获得巨型种子
3 周前By尊渡假赌尊渡假赌尊渡假赌

热工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

SublimeText3 Linux新版

SublimeText3 Linux新版

SublimeText3 Linux最新版

SecLists

SecLists

SecLists是最终安全测试人员的伙伴。它是一个包含各种类型列表的集合,这些列表在安全评估过程中经常使用,都在一个地方。SecLists通过方便地提供安全测试人员可能需要的所有列表,帮助提高安全测试的效率和生产力。列表类型包括用户名、密码、URL、模糊测试有效载荷、敏感数据模式、Web shell等等。测试人员只需将此存储库拉到新的测试机上,他就可以访问到所需的每种类型的列表。

WebStorm Mac版

WebStorm Mac版

好用的JavaScript开发工具

SublimeText3 英文版

SublimeText3 英文版

推荐:为Win版本,支持代码提示!