深入理解之Vue nextTick

一.定义【nextTick, 事件循环】

nextTick的由来
由于vue是数据驱动视图更新,是异步的,即修改数据的当下,视图不会立刻更新,会加入任务队列中,等同一事件循环中的所有数据变化完成之后,再统一进行视图更新
nextTick的触发时机
在同一事件循环中的数据变化后,dom完成更新,立即执行nextTick内的任务队列
应用场景
需要在视图更新之后,基于新的视图(DOM)进行操作

主线程完成同步任务的执行,将异步任务加入到任务队列中,主线程完成同步任务后,从任务队列中提取队首的任务(macrotask),放入主线程执行栈中,执行完毕后,再从任务队列中提取任务(macrotask),重复该操作,该过程称为事件循环

简单总结:

同步代码执行——》查找异步队列(macrotask queue),推入执行栈,执行callback1[事件循环1]——》查找异步队列(macrotask queue),推入执行栈,执行callback2[事件循环2]...

即每一个异步callback,最终都会形成自己独立的一个事件循环
任务队列的类型
  • microtask queue(微任务)promise MutationObserver nextTick
    唯一,整个事件循环中,仅存在一个队列,执行为同步按队列顺序执行
  • macrotask queue(宏任务)setTimeout setIntrval script
    不唯一,存在一定的优化级(用户I/O部分优先级更高),异步执行

个人总结: 执行栈按顺序执行,碰到同步任务直接执行,碰到异步任务,Marco task 加入 宏任务队列, micro task 加入 微任务队列——》
执行栈同步任务按顺序执行完成后,调用微任务队列中的任务按顺序执行(先进先出)——》
以上完成一次事件循环——》
从宏任务队列中提出首个宏任务进行第二次事件循环——》
重复上面的操作

案例:
<template>
    <div>
        <ul>
            <li v-for="item in list1">{{item}}</li>
        </ul>
        <ul>
            <li v-for="item in list2">{{item}}</li>
        </ul>

    </div>
</template>
<script type="text/javascript">
export default {
    data() {
        return {
            list1: [],
            list2: [],
        }
    },
    created() {
        this.composeList12()
        this.composeList34()
        this.$nextTick(function() {
            // DOM 更新了
            console.log('finished test ' + new Date().toString())
            console.log(document.querySelectorAll('li').length)
        })
    },
    methods: {
        composeList12() {
            let me = this
            let count = 10000

            for (let i = 0; i < count; i++) {
                Vue.set(me.list1, i, 'I am a 测试信息~~啦啦啦' + i)
            }
            console.log('finished list1 ' + new Date().toString())

            for (let i = 0; i < count; i++) {
                Vue.set(me.list2, i, 'I am a 测试信息~~啦啦啦' + i)
            }
            console.log('finished list2 ' + new Date().toString())

            this.$nextTick(function() {
                // DOM 更新了
                console.log('finished tick1&2 ' + new Date().toString())
                console.log(document.querySelectorAll('li').length)
            })
        },
        composeList34() {
            let me = this
            let count = 10000

            for (let i = 0; i < count; i++) {
                Vue.set(me.list3, i, 'I am a 测试信息~~啦啦啦' + i)
            }
            console.log('finished list3 ' + new Date().toString())

            this.$nextTick(function() {
                // DOM 更新了
                console.log('finished tick3 ' + new Date().toString())
                console.log(document.querySelectorAll('li').length)
            })

            setTimeout(me.setTimeout1, 0)
        },
        setTimeout1() {
            let me = this
            let count = 10000

            for (let i = 0; i < count; i++) {
                Vue.set(me.list4, i, 'I am a 测试信息~~啦啦啦' + i)
            }
            console.log('finished list4 ' + new Date().toString())

            me.$nextTick(function() {
                // DOM 更新了
                console.log('finished tick4 ' + new Date().toString())
                console.log(document.querySelectorAll('li').length)
            })
        }
    }
}
</script>
// 打印结果
> finished list1
> finished list2
> finished list3 
> finished tick1&2
> 30000
> finished tick3
> 30000
> finished test
> 30000
> finished list4
> finished tick4
> 40000



文章参考:
https://www.cnblogs.com/hity-tt/p/6729118.html
http://www.cnblogs.com/hity-tt/p/6733062.html

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 13,807评论 1 32
  • iOS多线程编程 基本知识 1. 进程(process) 进程是指在系统中正在运行的一个应用程序,就是一段程序的执...
    陵无山阅读 11,329评论 1 14
  • 找了一个实习,去公司做数据的可视化,就是用iview-admin,Echarts做一下展示。中间遇到了一个问题数据...
    小白小白啦阅读 12,765评论 1 8
  • 前言 为何单线程? 因为如果在DOM操作中,有两个线程一个添加节点,一个删除节点,浏览器并不知道以哪个为准,所以只...
    nawussika阅读 9,713评论 1 8
  • 天刚蒙蒙亮,妈妈就把我叫起。说趁星期天让我跟她到集市上《卖葱叶》去。 迷迷糊糊睁开双眼,看看窗外,一片漆黑,实在太...
    禅雨616阅读 4,903评论 8 18