本文章主要记录本人在使用VUE中$nextTick来解决dom更新相关问题以及相关技术的延伸。近期我在使用vue进行开发的过程中,遇到了这样的一个需求:
在地图上添加一个覆盖物,覆盖物的内容是一个dom元素
一 、问题描述
拿到这个问题时,并没有多想,觉得只要先在页面上添加一个dom元素,再放到作为覆盖物的内容添加到地图上即可。代码如下:
模板:
VUE:
添加一个dom
添加overlay,其内容是刚刚添加的dom
代码很简单,满怀信心,一看结果:dom渲染出来了,但是overlay里面没有内容,
我已经将dom作为overlay的内容传进来了,为什么没有在overlay里面展示出来呢?
二、定位问题
于是开始调试定位问题,发现:当数据中已经添加了新dom的数据后,并没有立即将dom渲染出,通过id拿到的dom为null,因此这时添加的overlay内容为空
当时想,是不是因为异步的问题导致的,遂写了个定时:
发现在js中增加了一个dom之后,dom渲染到页面上,定时结束,该dom被添加到overlay中,添加定时可以实现我们的需求,但加定时dom从渲染出来到被作为内容添加到overlay中回发生肉眼可见的位置移动,于是开始在网络的海洋中遨游(找度娘拯救),并且在前辈同事的代码中,看到了他使用$nextTick来应对数据---dom之间这个问题
我们看下把延迟换成nextTick效果如何呢:
完美解决?那我们看看是为什么呢,上网百度后,才知道,这是跟vue中的数据变化===》页面变化这个过程中的时间周期问题相关的,vue的数据绑定这个大家都知道的,当js中我们对数据做了更新,页面并不立即进行重新渲染dom,因此这时候立即去拿新的dom是拿不到的,但是vue提供了nextTick这个方法来处理类似问题
Vue.$nextTick(callback)
Vue 异步执行 DOM 更新。只要观察到数据变化,Vue 将开启一个队列,并缓冲在同一事件循环中发生的所有数据改变。
例如,当你设置vm.someData = 'new value',该组件不会立即重新渲染。当刷新队列时,组件会在事件循环队列清空时的下一个“tick”更新。多数情况我们不需要关心这个过程,但是如果你想在 DOM 状态更新后做点什么,这就可能会有些棘手。虽然 Vue.js 通常鼓励开发人员沿着“数据驱动”的方式思考,避免直接接触 DOM,但是有时我们确实要这么做。为了在数据变化之后等待 Vue 完成更新 DOM ,可以在数据变化之后立即使用Vue.nextTick(callback) 。这样回调函数在 DOM 更新完成后就会调用。
关于nextTick的源码分析,网上有一篇比较全面的介绍,附上链接:
nextTick的源码分析