先看一个以下的例子:
<!DOCTYPE>
<html>
<head>
<title>vue-exe</title>
<meta charset="utf-8">
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
{{a}}
<button @click="changeNum">点击改变值<button>
</div>
<script>
var app = new Vue({
el: "#app",
data: {
a: 1,
},
created() {
<!-- console.log('created:', this.$el.innerText) -->
this.$nextTick(function (){
console.log('created-nextTick:', this.$el.innerText)
})
},
mounted() {
console.log('mounted:', this.$el.innerText)
},
beforeUpdate() {
console.log('beforeUpdate-a:', this.a)
console.log('beforeUpdate:', this.$el.innerText)
},
updated() {
console.log('updated-a:', this.a)
console.log('updated:', this.$el.innerText)
},
methods: {
changeNum: function() {
this.a++
console.log('changeNum:', this.$el.innerText)
this.$nextTick(function (){
console.log('changeNum-nextTick:', this.$el.innerText)
})
}
}
})
</script>
</body>
</html>
- 首先,根据vue的生命周期,进入
created() -- data和methods都已经初始化了,但并未进行页面编译和挂载,所以,1、你在created()内访问dom元素内容会报错,就是我们注释掉的那条语句;2、我们同时运行nextTick的语句,后面看看它会打印什么
接着进入
mounted() -- 页面初始化完成了,data和methods等等都和页面元素挂钩上了,此时,访问dom元素内容可以打印出来。
页面初始化完成,看看打印出了什么
你会发现,先打印了mounted中的语句,而后,竟然执行了created中使用了this.$nextTick的函数。从这里,其实大致可以看到,this.$nextTick就是让元素能访问时再访问。
- 接下来,我们点击按钮,让a加1,看看控制台打印出了啥
我们来一一分析以下,点击按钮后执行按钮事件:
changeNum() -- 首先打印了当前DOM元素的值,你会发现我改变了a,此时a为2,但你取到的dom元素值仍为1,很奇怪
beforeUpdaate() -- 接下来进入到了beforeUpdate阶段,a值已改,但取到的dom元素值仍为1
updated() -- 最后进入了updated阶段,a值已改,dom值也刷新了
changeNum() -- 最后,执行了changeNum()中的this.$nextTick,取到了dom刷新后的值。
从上面的例子,可以很清晰地看出nextTick的用途:
- 等待dom元素能访问时再访问元素,经常用在条件渲染元素值改变后立即访问该dom元素
- dom元素绑定值更新后,等待值更新到dom再访问dom值
从vue的官网上找到这段话,现在可以很好地理解:
可能你还没有注意到,Vue 在更新 DOM 时是异步执行的。只要侦听到数据变化,Vue 将开启一个队列,并缓冲在同一事件循环中发生的所有数据变更。如果同一个 watcher 被多次触发,只会被推入到队列中一次。这种在缓冲时去除重复数据对于避免不必要的计算和 DOM 操作是非常重要的。然后,在下一个的事件循环“tick”中,Vue 刷新队列并执行实际 (已去重的) 工作。
例如,当你设置
vm.someData = 'new value'
,该组件不会立即重新渲染。当刷新队列时,组件会在下一个事件循环“tick”中更新。多数情况我们不需要关心这个过程,但是如果你想基于更新后的 DOM 状态来做点什么,这就可能会有些棘手。虽然 Vue.js 通常鼓励开发人员使用“数据驱动”的方式思考,避免直接接触 DOM,但是有时我们必须要这么做。为了在数据变化之后等待 Vue 完成更新 DOM,可以在数据变化之后立即使用Vue.nextTick(callback)
。这样回调函数将在 DOM 更新完成后被调用。
以上。涉及到更深层次地源代码部分,还有待学习。