Vue中的$nextTick有什么作用

  • 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. n e x t T i c k ( ) 实例方法只需要通过 t h i s . nextTick()实例方法只需要通过 this. 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 是用来标识同一个时间只能执行一次

Vue中的$nextTick有什么作用_第1张图片

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

  • Promise.then 、
  • MutationObserver 、
  • setImmediate 、
  • setTimeout

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

Vue中的$nextTick有什么作用_第2张图片

无论是微任务还是宏任务,都会放到 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中的回调

总结

Vue.js 是一个基于组件化的前端框架,它使用虚拟 DOM 来实现高效的更新和渲染。在 Vue.js 中,nextTick 方法用于在 DOM 更新之后执行回调函数。

nextTick 的实现原理可以简单描述如下:

  1. 当我们修改 Vue 实例的数据时,Vue.js 会将这些数据的变化记录下来,并放入一个队列中。
  2. 在下一个事件循环中(即当前任务队列执行完毕后),Vue.js 会遍历队列中的数据变化,并进行相应的 DOM 更新。
  3. 在 DOM 更新完成后,Vue.js 会触发 nextTick 回调函数。

具体的实现细节如下:

  1. Vue.js 使用异步队列来管理数据变化的通知和 DOM 更新。当我们修改 Vue 实例的数据时,Vue.js 会将这个数据变化的回调函数(Watcher)放入一个异步队列中。
  2. 在下一个事件循环中,Vue.js 会遍历异步队列中的回调函数,依次执行它们。
  3. 在执行每个回调函数之前,Vue.js 会先检查当前是否已经有一个异步任务正在执行。如果有,则将新的回调函数添加到队列的末尾;如果没有,则创建一个新的异步任务,并将队列中的所有回调函数都添加到该任务中。
  4. 在异步任务执行过程中,Vue.js 会对数据变化进行批量处理,以减少 DOM 更新的次数和性能开销。这样可以将多个数据变化合并为一个 DOM 更新操作,提高渲染效率。
  5. 在所有回调函数执行完毕后,Vue.js 会触发 nextTick 回调函数。

总结起来,nextTick 的实现原理就是利用异步队列和事件循环机制来延迟执行回调函数,以确保在 DOM 更新完成后再执行相应的操作。这样可以保证我们在使用 nextTick 时能够获取到最新的 DOM 结构。

你可能感兴趣的:(前端杂货铺,前端面试题,vue.js,前端,javascript)