这个api的源码早就看过了,但是一直没有总结,这里总结一下。这个api如何使用NextTick在Vue中有两种用法,一种作为全局方法Vue.nextTick使用,另一种挂载在组件实例上,由vm.$nextTick使用。当作为实例方法调用时,回调的this会自动绑定到调用它的实例。参数://{Function}[callback]//{Object}[context]Vue.nextTick([callback,context])用法:在下一个DOM更新周期结束后执行延迟回调。修改数据后立即使用此方法获取更新后的DOM。//修改数据vm.msg='Hello'//DOM未更新Vue.nextTick(function(){//DOM已更新})从2.1.0开始添加:如果没有提供回调并且在一个环境中支持Promise,返回一个Promise。//作为Promise使用(2.1.0后新增,详见下篇小贴士)Vue.nextTick().then(function(){//DOM更新})源码解析Vue.nextTick的源码在这个目录下:node_modules/vue/src/core/util/next-tick.js上的代码建议从第33行开始:lettimerFuncif(typeofPromise!=='undefined'&&isNative(Promise)){constp=Promise.resolve()timerFunc=()=>{p.then(flushCallbacks)if(isIOS)setTimeout(noop)}isUsingMicroTask=true}elseif(!isIE&&typeofMutationObserver!=='undefined'&&(isNative(MutationObserver)||MutationObserver.toString()==='[objectMutationObserverConstructor]')){letcounter=1constobserver=newMutationObserver(flushCallbacks)consttextNode=document.createTextNode(String(counter))观察者.observe(textNode),{characterData:true})timerFunc=()=>{counter=(counter+1)%2textNode.data=String(counter)}isUsingMicroTask=true}elseif(typeofsetImmediate!=='undefined'&&isNat我(设置Immediate)){timerFunc=()=>{setImmediate(flushCallbacks)}}else{timerFunc=()=>{setTimeout(flushCallbacks,0)}}这部分逻辑很简单,就是嗅探环境和依次检测Promise->MutationObserver->setImmediate->setTimeout存在,找到就使用,从而判断回调函数队列使用哪个api异步执行,再看87行nextTick方法定义:exportfunctionnextTick(cb?:Function,ctx?:Object){让_resolve回调。push(()=>{if(cb){try{cb.call(ctx)}catch(e){handleError(e,ctx,'nextTick')}}elseif(_resolve){_resolve(ctx)}})if(!pending){pending=truetimerFunc()}//$flow-disable-lineif(!cb&&typeofPromise!=='undefined'){returnnewPromise(resolve=>{_resolve=resolve})}}上面的代码中,由于新增了返回Promise的逻辑,所以有点复杂。可以直接看到如下简化逻辑:,ctx,'nextTick')}})if(!pending){pending=truetimerFunc()}}当nextTick函数接收到回调函数时,先不要调用,而是push到数组中的全局回调中.在nextTick方法结束时,会调用timerFunc方法。这个方法其实就是刚才嗅探环境时选择的api。以Promise为例,timerFunc方法应该是这样的:constp=Promise.resolve()lettimerFunc=()=>{p.then(flushCallbacks)if(isIOS)setTimeout(noop)}flushCallbacks方法将在下一轮事件循环中执行。让我们再看看flushCallbacks方法定义:constcallbacks=[]letpending=falsefunctionflushCallbacks(){pending=falseconstcopies=callbacks.slice(0)callbacks.length=0for(leti=0;i
