vue2從數(shù)據(jù)變化到視圖變化之nextTick使用詳解_第1頁
vue2從數(shù)據(jù)變化到視圖變化之nextTick使用詳解_第2頁
vue2從數(shù)據(jù)變化到視圖變化之nextTick使用詳解_第3頁
vue2從數(shù)據(jù)變化到視圖變化之nextTick使用詳解_第4頁
vue2從數(shù)據(jù)變化到視圖變化之nextTick使用詳解_第5頁
已閱讀5頁,還剩2頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

第vue2從數(shù)據(jù)變化到視圖變化之nextTick使用詳解目錄引言1、vue中nextTick的使用場(chǎng)景2、vue中nextTick在哪里定義3、vue中nextTick的實(shí)現(xiàn)原理(1)callbacks的定義(2)timerFunc的定義(3)cb未傳入的處理4、vue中nextTick的任務(wù)分類小結(jié)

引言

nextTick在vue中是一個(gè)很重要的方法,在newVue實(shí)例化的同步過程中,將一些需要異步處理的函數(shù)推到異步隊(duì)列中去,可以等newVue所有的同步任務(wù)執(zhí)行完后,再執(zhí)行異步隊(duì)列中的函數(shù)。

1、vue中nextTick的使用場(chǎng)景

借用vue.js官網(wǎng)中例子:

Vponent("example",{

template:"span{{message}}/span",

data:function(){

return{

message:"未更新"

methods:{

updateMessage:function(){

this.message="已更新";

console.log(this.$el.textContent);//='未更新'

this.$nextTick(function(){

console.log(this.$el.textContent);//='已更新'

例子中顯示數(shù)據(jù)變化后直接訪問節(jié)點(diǎn)內(nèi)容是未更新,當(dāng)使用了this.$nextTick包裹后訪問節(jié)點(diǎn)內(nèi)容是已更新,可以看出如果需要拿到數(shù)據(jù)變化后的節(jié)點(diǎn),則需要使用this.nextTick,這就是nextTick的使用場(chǎng)景。

那么,$nextTick是從哪里定義的?

2、vue中nextTick在哪里定義

在vue源碼initGlobalAPI(Vue)過程中:

import{nextTick}from'../util/index'

//...

Vue.nextTick=nextTick

3、vue中nextTick的實(shí)現(xiàn)原理

/*@flow*/

/*globalsMutationObserver*/

import{noop}from'shared/util'

import{handleError}from'./error'

import{isIE,isIOS,isNative}from'./env'

exportletisUsingMicroTask=false

constcallbacks=[]

letpending=false

functionflushCallbacks(){

pending=false

constcopies=callbacks.slice(0)

callbacks.length=0

for(leti=0;icopies.length;i++){

copies[i]()

//Herewehaveasyncdeferringwrappersusingmicrotasks.

//In2.5weused(macro)tasks(incombinationwithmicrotasks).

//However,ithassubtleproblemswhenstateischangedrightbeforerepaint

//(e.g.#6813,out-intransitions).

//Also,using(macro)tasksineventhandlerwouldcausesomeweirdbehaviors

//thatcannotbecircumvented(e.g.#7109,#7153,#7546,#7834,#8109).

//Sowenowusemicrotaskseverywhere,again.

//Amajordrawbackofthistradeoffisthattherearesomescenarios

//wheremicrotaskshavetoohighapriorityandfireinbetweensupposedly

//sequentialevents(e.g.#4521,#6690,whichhaveworkarounds)

//orevenbetweenbubblingofthesameevent(#6566).

lettimerFunc

//ThenextTickbehaviorleveragesthemicrotaskqueue,whichcanbeaccessed

//viaeithernativePromise.thenorMutationObserver.

//MutationObserverhaswidersupport,howeveritisseriouslybuggedin

//UIWebViewiniOS=9.3.3whentriggeredintoucheventhandlers.It

//completelystopsworkingaftertriggeringafewtimes...so,ifnative

//Promiseisavailable,wewilluseit:

/*istanbulignorenext,$flow-disable-line*/

if(typeofPromise!=='undefined'isNative(Promise)){

constp=Promise.resolve()

timerFunc=()={

p.then(flushCallbacks)

//InproblematicUIWebViews,Promise.thendoesn'tcompletelybreak,but

//itcangetstuckinaweirdstatewherecallbacksarepushedintothe

//microtaskqueuebutthequeueisn'tbeingflushed,untilthebrowser

//needstodosomeotherwork,e.g.handleatimer.Thereforewecan

//"force"themicrotaskqueuetobeflushedbyaddinganemptytimer.

if(isIOS)setTimeout(noop)

isUsingMicroTask=true

}elseif(!isIEtypeofMutationObserver!=='undefined'(

isNative(MutationObserver)||

//PhantomJSandiOS7.x

MutationObserver.toString()==='[objectMutationObserverConstructor]'

//UseMutationObserverwherenativePromiseisnotavailable,

//e.g.PhantomJS,iOS7,Android4.4

//(#6466MutationObserverisunreliableinIE11)

letcounter=1

constobserver=newMutationObserver(flushCallbacks)

consttextNode=document.createTextNode(String(counter))

observer.observe(textNode,{

characterData:true

timerFunc=()={

counter=(counter+1)%2

textNode.data=String(counter)

isUsingMicroTask=true

}elseif(typeofsetImmediate!=='undefined'isNative(setImmediate)){

//FallbacktosetImmediate.

//Technicallyitleveragesthe(macro)taskqueue,

//butitisstillabetterchoicethansetTimeout.

timerFunc=()={

setImmediate(flushCallbacks)

}else{

//FallbacktosetTimeout.

timerFunc=()={

setTimeout(flushCallbacks,0)

exportfunctionnextTick(cb:Function,ctx:Object){

let_resolve

callbacks.push(()={

if(cb){

try{

cb.call(ctx)

}catch(e){

handleError(e,ctx,'nextTick')

}elseif(_resolve){

_resolve(ctx)

if(!pending){

pending=true

timerFunc()

//$flow-disable-line

if(!cbtypeofPromise!=='undefined'){

returnnewPromise(resolve={

_resolve=resolve

(1)callbacks的定義

在nextTick中首先在callbacks中推入進(jìn)行try{}catch(e){}捕捉錯(cuò)誤的回調(diào)函數(shù)。

(2)timerFunc的定義

然后,如沒有在pengding狀態(tài)時(shí),將pending置為true,并執(zhí)行timerFunc函數(shù),這個(gè)函數(shù)依次根據(jù)當(dāng)前瀏覽器執(zhí)行環(huán)境中支不支持Promise、MutationObserver和setImmediate方法進(jìn)行賦值,如果都不支持,則使用setTimeout。

第一步,如果瀏覽器支持Promise,constp=Promise.resolve(),然后timerFunc中定義p.then(flushCallbacks),通過p.then(flushCallbacks)自執(zhí)行的能力來誘發(fā)flushCallbacks;第二步,如果瀏覽器不支持Promise但支持MutationObserver,則其利用DOM屬性監(jiān)聽變化的能力,首先定義constobserver=newMutationObserver(flushCallbacks),并監(jiān)聽consttextNode=document.createTextNode(String(counter))的變化,timerFunc的執(zhí)行是通過修改textNode值來誘發(fā)flushCallbacks的執(zhí)行。第三步,以上兩者都不滿足,但瀏覽器支持立即執(zhí)行函數(shù)setImmediate,則通過timerFunc=()={setImmediate(flushCallbacks)}的方式來誘發(fā)flushCallbacks.第四步,以上條件都不滿足的時(shí)候,則通過timerFunc=()={setTimeout(flushCallbacks,0)}將定時(shí)器的延遲時(shí)間設(shè)置為0進(jìn)行flushCallbacks的誘發(fā)。

以上四步中提到的的flushCallbacks函數(shù),其中pending=false表示同步任務(wù)已經(jīng)執(zhí)行結(jié)束,開始了異步隊(duì)列的執(zhí)行。constcopies=callbacks.slice(0)進(jìn)行異步事件的淺拷貝,并將異步隊(duì)

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論