目录

一,前言

二,什么是异步更新队列

三,使用异步更新队列

四,结尾


一,前言

这一篇介绍有关异步更新队列的知识,通过异步更新队列的学习和研究能够更好的理解Vue的更新机制
  •  

二,什么是异步更新队列

先看一个例子:

<div id="app">
    <div id="div" v-if="show">测试文本(默认隐藏)</div>
    <Button @click="toggle">显示Div</Button>
</div>

<script type="text/javascript">
    var vm = new Vue({
        el: '#app',
        data: {
            // 控制div是否渲染,默认隐藏
            show: false
        },
        methods:{
            toggle: function () {
                this.show = true;
                var content = document.getElementById('div').innerHTML;
                alert("content = " + content)
            }
        }
    })
</script>
一个很简单的例子,由v-if控制div是否被渲染,默认不渲染,点击按钮对div显示/隐藏做更改
  •  

按照以往的认识:

当点击按钮切换div显隐时,由于控制显隐的变量show被置为true,div会被渲染
document.getElementById('div').innerHTML能够获取到内部html

实际执行结果

当点击按钮时,控制显隐的变量show被置为true
随后document.getElementById('div').innerHTML时会报错
错误原因:获取不到div元素

当再次点击按钮时,弹出alert:


 

这里就涉及到了Vue异步更新队列的概念了:

Vue在观察到数据发生变化时,并不是直接去更新DOM,
而是会开启一个队列,并缓冲在同一事件循环中发生的所有数据变化

在缓冲时,会去除重复的数据,避免多余的计算和DOM操作,
在下一个事件循环tick中,刷新队列并执行已去重的工作

报错原因:

所以,在执行this.show=true时,div还未被创建出来,
直到下一个Vue事件循环时才开始创建

这种查重机制使降低了Vue的开销:

for循环动态改变数据100次,查重后,只会执行最后一次改变,
如果没有查重机制,页面将重绘100此,而前99此是无用的,会加大开销

异步更新队列实现的选择:

由于浏览器的差异,Vue会根据当前浏览器环境选择原生Promise.then和MutationObserver
如果两者都不支持,会采用SetTimeout进行替代

三,使用异步更新队列

了解了Vue异步更新DOM的原理之后,使用Vue提供的异步队列对上边的例子进行修改

刚刚分析了报错的原因:在show=ture是div未被创建,在下一个事件循环中才开始创建
Vue提供了$nextTick告知DOM何时更新完成,我们可以在$nextTick中进行div获取

<div id="app">
    <div id="div" v-if="show">测试文本(默认隐藏)</div>
    <Button @click="toggle">显示Div</Button>
</div>

<script type="text/javascript">
    var vm = new Vue({
        el: '#app',
        data: {
            // 控制div是否渲染,默认隐藏
            show: false
        },
        methods:{
            toggle: function () {
                this.show = true;
                // $nextTick:通知DOM更新完成
                this.$nextTick(function () {
                    var content = document.getElementById('div').innerHTML;
                    alert("content = " + content)
                })
            }
        }
    })
</script>
通过简单的修改后,首次点击获取内容不再报错

四,结尾

通过对异步更新队列的介绍,加深了对子组件渲染的了解
异步更新队列是一个非常有用的东西,在使用第三方库时,很多并不是数据驱动DOM的
这时就要使用JS原声库中创建,更新,销毁的生命周期,通过$nextTick与Vue配合使用

本面试题为前端常考面试题,后续有机会继续完善。我是歌谣,一个沉迷于故事的讲述者。

欢迎一起私信交流。

“睡服“面试官系列之各系列目录汇总(建议学习收藏)