You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Vue.nextTick([callback,context])•参数:◦{Function}[callback]◦{Object}[context]•用法:在下次DOM更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的DOM。// 修改数据•vm.msg='Hello'•// DOM 还没有更新•Vue.nextTick(function(){•// DOM 更新了•})••// 作为一个 Promise 使用 (2.1.0 起新增,详见接下来的提示)•Vue.nextTick()•.then(function(){•// DOM 更新了•})
首先来看一下 vue 提供的 nextTick api
2.1.0 起新增:如果没有提供回调且在支持 Promise 的环境中,则返回一个 Promise。请注意 Vue 不自带 Promise 的 polyfill,所以如果你的目标浏览器不原生支持 Promise (IE:你们都看我干嘛),你得自己提供 polyfill。
带问题阅读
正文
nextTick源码分析
宏任务,微任务和事件循环
JavaScript是一个单进程的语言,同一时间不能处理多个任务,所以何时执行宏任务,何时执行微任务?我们需要有这样的一个判断逻辑存在。
这个就像去银行办业务一样,先要取号进行排号。一般上边都会印着类似:“您的号码为XX,前边还有XX人。
因为柜员同时职能处理一个来办理业务的客户,这时每一个来办理业务的人就可以认为是银行柜员的一个宏任务来存在的,当柜员处理完当前客户的问题以后,继续处理下一位,也就是下一个宏任务的开始。
而一个宏任务在执行的过程中,是可以添加一些微任务的,就像在柜台办理业务,你前边的一位老大爷可能在存款,在存款这个业务办理完以后,柜员会问老大爷还有没有其他需要办理的业务,这时老大爷想了一下:“最近P2P爆雷有点儿多,是不是要选择稳一些的理财呢”,然后告诉柜员说,要办一些理财的业务,这时候柜员肯定不能告诉老大爷说:“您再上后边取个号去,重新排队”。
所以本来快轮到你来办理业务,会因为老大爷临时添加的::任务::而往后推。
理解下面代码
以上注释过程结束之后遇到一个问题
setTimeout 和 Promise 这两个兄弟 因为银行规定 有事走的人 回来的时候要重新排一个队 (任务队列)
并且规定,先办理过一些任务的人需要继续办理的人优先办理,所以 Promise 排在了 setTimeout 前面继续办理业务
回到现实的总结:
JavaScript的单线程,单线程就意味着,所有任务需要排队,前一个任务结束,才会执行后一个任务。如果前一个任务耗时很长,后一个任务就不得不一直等着。
如果排队是因为计算量大,CPU忙不过来,倒也算了,但是很多时候CPU是闲着的,因为IO设备(输入输出设备)很慢(比如Ajax操作从网络读取数据),不得不等着结果出来,再往下执行。
JavaScript语言的设计者意识到,这时主线程完全可以不管IO设备,挂起处于等待中的任务,先运行排在后面的任务。等到IO设备返回了结果,再回过头,把挂起的任务继续执行下去。
于是,所有任务可以分成两种,一种是同步任务(synchronous),另一种是异步任务(asynchronous)。同步任务指的是,在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务;异步任务指的是,不进入主线程、而进入”任务队列”(task queue)的任务,只有”任务队列”通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行。
(1)所有同步任务都在主线程上执行,形成一个执行栈
(2)主线程之外,还存在一个”任务队列”(task queue)。只要异步任务有了运行结果,就在”任务队列”之中放置一个事件。
(3)一旦”执行栈”中的所有同步任务执行完毕,系统就会读取”任务队列”,看看里面有哪些事件。那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行。
(4)主线程不断重复上面的第三步。
主线程从”任务队列”中读取事件,这个过程是循环不断的,所以整个的这种运行机制又称为::Event Loop::(事件循环)。
理解事件循环机制后,在来回看 nextTick 实现的原理
通过前面的了解,我们发现了
Vue
的更新操作默认会将执行渲染操作的函数添加到微任务队列中,而微任务的执行时机优先于宏任务。Ok 经过测试大家发现是能实现正常使用的,但是这是在理想情况下,通过源码我们可以看到 nextTick 最后保底实现方式是通过 setTimeout 来执行 flushCallbacks
如果将这部分vue源码默认成settimeout实现就并不能得多上面demo的结果。
所以有时候代码能运行,并不意味着他是稳定的,希望大家都能了解原理,举一反三。
#技术笔记/博客
The text was updated successfully, but these errors were encountered: