Vue.nextTick 到底有什么用?
Vue 虽然采用了“数据驱动”的思想,但我们依然需要在某些情况下进行少量的 DOM 操作。在 Vue 中,异步执行 DOM 更新。多数情况下,我们并不需要考虑这个过程,但是如果我们的某个操作中,DOM1 的数据变化后,DOM2 需要从 DOM1 的 DOM 结构中获取数据,就会发现数据并没有实时更新,这时候就需要用到 nextTick
我们都知道大多数情况下 Vue 数据变化后,相应的 html 也随着发生变化。事实上,当数据发生改变后,对应的 html 并没有立即重新渲染,
而是开启一个队列,并将改变的数据缓存在同一事件循环中,当刷新队列时,组件会在事件循环队列清空时的下一个“tick”更新。
如果同一个 watcher 被多次触发,只会被推入到队列中一次。这种在缓冲时去除重复数据对于避免不必要的计算和 DOM 操作上非常重要。
Vue.nextTick(callback)
。这样回调函数在 DOM 更新完成后就会调用。页面显示如下:
但是如果我们把 mounted 钩子改为 created 钩子:
我们发现 DOM 操作失败,页面内容并未更改,在控制台上报错:未找到相应的DOM节点:
现在我们给 created 钩子稍作修改,加上 this.$nextTick, 在它的回调函数中写我们的 DOM 操作:
加上 nextTick 后,又可以正常显示:
【分析】:
在created()
钩子函数执行的时候DOM 其实并未进行任何渲染,而此时进行DOM操作无异于徒劳,所以此处一定要将DOM操作的js代码放进Vue.nextTick()
的回调函数中。与之对应的就是mounted()
钩子函数,因为该钩子函数执行时所有的DOM挂载和渲染都已完成,此时在该钩子函数中进行任何DOM操作都不会有问题 。
再来另外一个场景:
我们现在给按钮添加点击事件,事件触发后,相应 DOM 的数据发生更改,并查看此刻该 DOM 节点数据的变化情况:
当我们第一次点击绑定事件的 DOM 后,该按钮的 innerHTML 的文字发生改变,更改为: NEW MESSAGE,但是此时打印该 DOM 所绑定的却是点击之前的旧的数据;
当我们再次点击该元素时,控制台打印的该元素绑定的数据才是新的更改的数据
总结:
1. 在Vue生命周期的created()
钩子函数进行的DOM操作一定要放在Vue.nextTick()
的回调函数中
2. 在数据变化后要执行的某个操作,而这个操作需要使用随数据改变而改变的DOM结构的时候,这个操作都应该放进Vue.nextTick()
的回调函数中。