vue.js中的$nextTick是异步更新,今天看看这个是怎么玩的。先来看一个demo:

我们看看页面结构和关键代码:

上面的demo主要测试的是在vue中,我改变一个变量的值,是否会立马更新到页面上。

然而实际上vue是不会改一个变量就更新一个的,它的内部会维护一个队列去收集这些改变,然后一起去处理它们。这样就会导致你改了一个变量,然后立马去获取DOM上的内容,就会发现不是最新的,就如同上面的msg1和msg3一样。

$nextTick源码分析

$nextTick主要原理是异步更新,说的直白点有点类似于我们平常用的setTimeout(fn,0):当你处理一个比较耗时的操作的时候,为了保证能够在耗时操作完成的时候做某些事情,一般会用setTimeout(fn,0)。因为vue的内部就是先收集这些变化的变量,然后处理它们(去重等),处理完之后才会修改DOM上的内容,我们可以把它们理解成一个比较耗时的同步操作,然后$nextTick就是把一些处理方法添加到耗时操作完成后去执行。

先来看看$nextTick源码:

源码内部和我们刚才分析的思路差不多,它先会把一些要异步处理的方法收集起来,然后去监听当前同步操作何时完成,完成之后就再去执行那些异步回调。

只不过$nextTick中有三种监听同步操作完成的方法:Promise.resolve().then() , setTimeout(fn,0) , MutationObserver。前面两种的话,在我之前的一篇文章中有介绍: Promise.resolve()和setTimeout(fn,0),今天主要介绍一下MutationObserver。

MutationObserver

MutationObserver主要是用来监听一个DOM节点的内容/子节点/属性变化的,详细介绍可以看这篇文章 Mutation Observer API。用法也是非常的简单,先new一个实例:var observe = new MutationObserver(fn(){/*回调方法*/}),然后利用实例的observe方法去监听你要监听的对象,可以配置要监听什么内容:

childList:子节点的变动(指新增,删除或者更改)。

attributes:属性的变动。

characterData:节点内容或节点文本的变动。

监听到有变化的话,就会执行回调函数。不过MutationObserver的回调多次触发只会回调一次,例如你去监听一个DOM节点的子节点变化,每次增加一个子节点,一共增加10次,这个时候回调只会触发一次:

关键代码如下:

除次之外MutationObserver的回调还是异步回调,例如你自己创建一个TextNode(文本节点),然后去监听它的内容变化,如果此时页面上有同步操作,例如大量计算,DOM操作等,它的回调会等到同步操作完成时触发,$nextTick中的源码异步监听也是用的这个原理:

关键代码如下:

我们可以发现,哪怕我们是先执行observe()去改变TextNode文本的内容,它的回调也是等到当前同步操作完成是触发。

$nextTick vs created

在vue的created钩子中,如果要操作DOM元素的话,需要放在$nextTick里面,因为此时DOM还没有渲染好:

其他文章

0
我要评论

评论

返回
×

我要评论

回复:

昵称:(昵称不超过20个字)

图片:

提交
还可以输入500个字