vue.nextTick()

71 阅读1分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第3天,点击查看活动详情 >>

定义

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

在vue改变dom元素结构之后使用vue。$nextTick()方法来实现dom数据更新后延迟执行后续代码。

原因

vue的响应式不是数据变化后dom立即变化,而是异步执行dom更新,也就是等同一时间循环中的所有数据变化完成后,再统一进行视图更新。

  • 事件执行机制
    • 同步任务在主线程上直接执行,一个执行栈
    • 异步任务被解析后形成回调函数保存在另一个任务队列中,此任务队列包括宏任务和微任务
    • 主线程的执行栈所有任务执行完毕时会不断读取和执行任务队列中的异步任务

过程

  • 调用$nextTick()相当于向callbacks添加回调函数等待执行

  • 判断$nextTick()里面的内容是宏任务还是微任务,等待下一次事件循环时执行

  • 按顺序执行callbacks中的回调函数

ps:

  • $nextTick()把内容优先添加到微任务中执行,所以总是先于setTimeout执行
  • 在DOM更新后,nextTick()先使用Promise.thenMutationObserversetImmediate判断,如果环境不支持再用setTimeout代替,相当于nextTick()先使用Promise.then、MutationObserver 和 setImmediate判断,如果环境不支持再用setTimeout代替,相当于nextTick()包含setTimeout

场景

需要在视图更新之后,基于新的视图进行操作,随数据改变而改变的dom应用场景,应该把这些操作都放在this.$nextTick()里面

  • 想要打印数据更改后的dom
<template>
  <div>
  	<p ref='value'>{{value}}</p>
		<button @click="changeValue">click</button>
  </div>
</template>
<sctipt>
	data() {
      return {
        value:'change'
      }
  },
	methods: {
    changeValue() {
      this.value = 'changed'
      console.log(this.$refs.value.innerText,'methods')
  		this.$nextTick() {
				console.log(this.$refs.value.innerText,'methods in nextTick')
      }
    }
  },
  created() {
  	console.log(this.$refs.value.innerText,'created')
  	this.$nextTick() {
			console.log(this.$refs.value.innerText,'created in nextTick')
    }
  },
  mounted() {
  	console.log(this.$refs.value.innerText,'mounted')
  	this.$nextTick() {
			console.log(this.$refs.value.innerText,'mounted in nextTick')
    }
  },
</script>