this.$nextTick()

333 阅读1分钟

这是我参与11月更文挑战的第4天,活动详情查看:2021最后一次更文挑战

因为热爱所以坚持~

前言

xdm,连载我的故事哈哈~ 同事离职,被迫接手一个长期维护型项目,天天都很崩溃,做梦都是相关内容,于是今天跟组长提了不想干这个项目了,进而萌生提桶的想法。但是前辈特别好,希望我可以坚持坚持,我也确实不想辜负他的好意,就再待两天看看吧!今天学this.$nextTick(),项目代码中看到过好多次,一直没研究,正好学一下~

nextTick()

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

import { createApp, nextTick } from 'vue'
const app = createApp({
  setup() {
    const message = ref('Hello!')
    const changeMessage = async newMessage => {
      message.value = newMessage
      // 这里获取DOM的value是旧值
      await nextTick()
      // nextTick 后获取DOM的value是更新后的值
      console.log('Now DOM is updated')
    }
  }
})

JS执行机制:单线程,同步异步,来自:vue3js.cn/global/next…

  • (1)所有同步任务都在主线程上执行,形成一个执行栈(execution context stack)。
  • (2)主线程之外,还存在一个"任务队列"(task queue)。只要异步任务有了运行结果,就在"任务队列"之中放置一个事件。
  • (3)一旦"执行栈"中的所有同步任务执行完毕,系统就会读取"任务队列",看看里面有哪些事件。那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行。
  • (4)主线程不断重复上面的第三步

vue 里的nextTick() 基于语言执行机制实现,直接创建一个异步任务,那么nextTick自然就达到在同步任务后执行的目的:

const p = Promise.resolve()
export function nextTick(fn?: () => void): Promise<void> {
  return fn ? p.then(fn) : p
}

官网上接下来在分析源码,好复杂~总的来说应该是:nextTick(),是将回调函数延迟在下一次dom更新数据后调用,也就是:当数据更新了,在dom中渲染后,自动执行该函数。

举例

<div @click="changeMsg() ref="test">{{message}}</div>
<script>
export default{
    data(){
        return{
            message:"origin"
        }
    },
    methods:{
        //没有用nextTick()
        changeMsg:function(){
            let _this = this;
            _this.message = "now";
            console.log(_this.$ref.test.innerText)//输出origin(this.$ref.test取指定DOM)
        },
        //使用了nextTick()
        changeMsg:function(){
            let _this = this;
            _this.message = "now";
            _this.nextTick(function(){
                console.log(_this.$ref.test.innerText)//输出now
            });
        }
    }
}
</script>

总结:vue实现响应式并不是数据发生变化之后 DOM 立即变化,而是按一定的策略进行 DOM 的更新。nextTick是在下次DOM更新循环结束之后执行延迟回调,在修改数据之后使用nextTick 是在下次 DOM 更新循环结束之后执行延迟回调,在修改数据之后使用 nextTick,则可以在回调中获取更新后的 DOM。