日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術文章
文章詳情頁

詳解Vue的異步更新實現原理

瀏覽:3日期:2022-10-17 10:47:08

最近面試總是會被問到這么一個問題:在使用vue的時候,將for循環中聲明的變量i從1增加到100,然后將i展示到頁面上,頁面上的i是從1跳到100,還是會怎樣?答案當然是只會顯示100,并不會有跳轉的過程。

怎么可以讓頁面上有從1到100顯示的過程呢,就是用setTimeout或者Promise.then等方法去模擬。

講道理,如果不在vue里,單獨運行這段程序的話,輸出一定是從1到100,但是為什么在vue中就不一樣了呢?

for(let i=1; i<=100; i++){console.log(i);}

這就涉及到Vue底層的異步更新原理,也要說一說nextTick的實現。不過在說nextTick之前,有必要先介紹一下JS的事件運行機制。

JS運行機制

眾所周知,JS是基于事件循環的單線程的語言。 執行的步驟大致是:

當代碼執行時,所有同步的任務都在主線程上執行,形成一個執行棧; 在主線程之外還有一個任務隊列(task queue),只要異步任務有了運行結果就在任務隊列中放置一個事件; 一旦執行棧中所有同步任務執行完畢(主線程代碼執行完畢),此時主線程不會空閑而是去讀取任務隊列。此時,異步的任務就結束等待的狀態被執行。 主線程不斷重復以上的步驟。

詳解Vue的異步更新實現原理

我們把主線程執行一次的過程叫一個tick,所以nextTick就是下一個tick的意思,也就是說用nextTick的場景就是我們想在下一個tick做一些事的時候。

所有的異步任務結果都是通過任務隊列來調度的。而任務分為兩類:宏任務(macro task)和微任務(micro task)。它們之間的執行規則就是每個宏任務結束后都要將所有微任務清空。 常見的宏任務有setTimeout/MessageChannel/postMessage/setImmediate,微任務有MutationObsever/Promise.then。

想要透徹學習事件循環,推薦Jake在JavaScript全球開發者大會的演講,保證講懂!

nextTick原理派發更新

大家都知道vue的響應式的靠依賴收集和派發更新來實現的。在修改數組之后的派發更新過程,會觸發setter的邏輯,執行dep.notify():

// src/core/observer/watcher.jsclass Dep {notify() { //subs是Watcher的實例數組 const subs = this.subs.slice() for(let i=0, l=subs.length; i<l; i++){ subs[i].update() } }}

遍歷subs里每一個Watcher實例,然后調用實例的update方法,下面我們來看看update是怎么去更新的:

class Watcher {update() { ... //各種情況判斷之后 else{ queueWatcher(this) } }}

update執行后又走到了queueWatcher,那就繼續去看看queueWatcher干啥了(希望不要繼續套娃了:

//queueWatcher 定義在 src/core/observer/scheduler.jsconst queue: Array<Watcher> = []let has: { [key: number]: ?true } = {}let waiting = falselet flushing = falselet index = 0export function queueWatcher(watcher: Watcher) {const id = watcher.id //根據id是否重復做優化 if(has[id] == null){ has[id] = true if(!flushing){ queue.push(watcher) }else{ let i=queue.length - 1 while(i > index && queue[i].id > watcher.id){ i-- } queue.splice(i + 1, 0, watcher) } if(!waiting){ waiting = true //flushSchedulerQueue函數: Flush both queues and run the watchers nextTick(flushSchedulerQueue) } }}

這里queue在pushwatcher時是根據id和flushing做了一些優化的,并不會每次數據改變都觸發watcher的回調,而是把這些watcher先添加到⼀個隊列⾥,然后在nextTick后執⾏flushSchedulerQueue。

flushSchedulerQueue函數是保存更新事件的queue的一些加工,讓更新可以滿足Vue更新的生命周期。

這里也解釋了為什么for循環不能導致頁面更新,因為for是主線程的代碼,在一開始執行數據改變就會將它push到queue里,等到for里的代碼執行完畢后i的值已經變化為100時,這時vue才走到nextTick(flushSchedulerQueue)這一步。

nextTick源碼

接著打開vue2.x的源碼,目錄core/util/next-tick.js,代碼量很小,加上注釋才110行,是比較好理解的。

const callbacks = []let pending = falseexport function nextTick (cb?: Function, ctx?: Object) { let _resolve callbacks.push(() => { if (cb) { try { cb.call(ctx) } catch (e) { handleError(e, ctx, ’nextTick’) } } else if (_resolve) { _resolve(ctx) } }) if (!pending) { pending = true timerFunc() }

首先將傳入的回調函數cb(上節的flushSchedulerQueue)壓入callbacks數組,最后通過timerFunc函數一次性解決。

let timerFuncif (typeof Promise !== ’undefined’ && isNative(Promise)) { const p = Promise.resolve() timerFunc = () => { p.then(flushCallbacks) if (isIOS) setTimeout(noop) } isUsingMicroTask = true} else if (!isIE && typeof MutationObserver !== ’undefined’ && ( isNative(MutationObserver) || // PhantomJS and iOS 7.x MutationObserver.toString() === ’[object MutationObserverConstructor]’)) { let counter = 1 const observer = new MutationObserver(flushCallbacks) const textNode = document.createTextNode(String(counter)) observer.observe(textNode, { characterData: true }) timerFunc = () => { counter = (counter + 1) % 2 textNode.data = String(counter) } isUsingMicroTask = true} else if (typeof setImmediate !== ’undefined’ && isNative(setImmediate)) { timerFunc = () => { setImmediate(flushCallbacks) }} else { timerFunc = () => { setTimeout(flushCallbacks, 0) }}

timerFunc下面一大片if else是在判斷不同的設備和不同情況下選用哪種特性去實現異步任務:優先檢測是否原生⽀持Promise,不⽀持的話再去檢測是否⽀持MutationObserver,如果都不行就只能嘗試宏任務實現,首先是setImmediate,這是⼀個⾼版本 IE 和 Edge 才⽀持的特性,如果都不⽀持的話最后就會降級為 setTimeout 0。

這⾥使⽤callbacks⽽不是直接在nextTick中執⾏回調函數的原因是保證在同⼀個 tick 內多次執⾏nextTick,不會開啟多個異步任務,⽽把這些異步任務都壓成⼀個同步任務,在下⼀個 tick 執⾏完畢。

nextTick使用

nextTick不僅是vue的源碼文件,更是vue的一個全局API。下面來看看怎么使用吧。

當設置 vm.someData = ’new value’,該組件不會立即重新渲染。當刷新隊列時,組件會在下一個事件循環tick中更新。多數情況我們不需要關心這個過程,但是如果你想基于更新后的 DOM 狀態來做點什么,這就可能會有些棘手。雖然 Vue.js 通常鼓勵開發人員使用數據驅動的方式思考,避免直接接觸 DOM,但是有時我們必須要這么做。為了在數據變化之后等待 Vue 完成更新 DOM,可以在數據變化之后立即使用Vue.nextTick(callback)。這樣回調函數將在 DOM 更新完成后被調用。

官網用例:

<div id='example'>{{message}}</div>

var vm = new Vue({ el: ’#example’, data: { message: ’123’ }})vm.message = ’new message’ // 更改數據vm.$el.textContent === ’new message’ // falseVue.nextTick(function () { vm.$el.textContent === ’new message’ // true})

并且因為$nextTick() 返回一個 Promise 對象,所以也可以使用async/await 語法去處理事件,非常方便。

以上就是詳解Vue的異步更新實現原理的詳細內容,更多關于vue 異步更新的資料請關注好吧啦網其它相關文章!

標簽: Vue
相關文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
国产乱人伦精品一区| 福利一区二区免费视频| 久久久久一区| 国产91精品对白在线播放| 久久国产亚洲| 夜夜嗨一区二区三区| 免费国产自线拍一欧美视频| 视频一区在线播放| 亚洲综合图色| 69堂免费精品视频在线播放| 国产欧美日韩精品一区二区免费| 国产精品99久久免费| 国产一区二区三区日韩精品| 国产精品成人a在线观看| 国产盗摄——sm在线视频| 另类欧美日韩国产在线| 水蜜桃久久夜色精品一区| 亚洲香蕉网站| 亚久久调教视频| 美女精品一区二区| 亚洲永久av| 国产一区观看| 日韩中文字幕| 久久免费精品| 激情丁香综合| 日韩福利视频一区| 黑森林国产精品av| 蜜桃视频欧美| 日本在线视频一区二区| 国产精品久久777777毛茸茸| 国产suv精品一区二区四区视频| 久久黄色影院| 亚洲日本国产| 精品91福利视频| 狠狠爱www人成狠狠爱综合网| 日本一不卡视频| 成人午夜在线| 模特精品在线| 久久婷婷国产| 黄色成人精品网站| 国产视频一区二| 欧美综合另类| 国产日韩欧美一区| 亚洲福利国产| 91精品国产一区二区在线观看| 四季av一区二区凹凸精品| 国产模特精品视频久久久久| 欧美精品二区| 亚洲欧美日韩国产| 精品高清久久| 中文字幕一区二区三区在线视频| 麻豆国产欧美日韩综合精品二区| 国产韩日影视精品| 另类小说一区二区三区| 美女被久久久| 日韩成人a**站| 日本一区二区三区视频在线看| 国产高潮在线| 日本在线不卡视频| 久久婷婷av| 欧美日韩精品一区二区三区视频 | 欧美日韩中出| 中文字幕系列一区| 国产丝袜一区| 国产视频一区在线观看一区免费| 久久av中文| 日韩中文字幕亚洲一区二区va在线| 精品美女视频| 97成人在线| 婷婷中文字幕一区| 久久亚洲黄色| 日韩av不卡在线观看| 亚洲女同中文字幕| 久久免费视频66| 婷婷久久免费视频| 欧美在线影院| 久久精品国产精品亚洲毛片| 亚洲一区二区三区中文字幕在线观看| 日韩免费小视频| 欧美国产专区| 日本三级亚洲精品| 国产一区二区高清| 91精品国产调教在线观看| 精品亚洲a∨一区二区三区18| 日本v片在线高清不卡在线观看| 91精品观看| 久久精品青草| 日韩一区二区三区免费| 欧美国产另类| 91精品日本| 日韩专区一卡二卡| 婷婷中文字幕一区| 久久久久久久久99精品大| 高清精品久久| 黄色网一区二区| 久久99精品久久久久久园产越南| 亚洲精品在线二区| 亚洲欧美网站| 国产视频一区在线观看一区免费| 99精品综合| 三级精品视频| 日韩成人综合| 日韩一区二区中文| 国产一区三区在线播放| 国产精品一区二区99| 日本午夜免费一区二区| 亚洲精品三级| 中文字幕av一区二区三区人| 六月丁香综合| 日韩在线一区二区| 六月丁香综合| 蜜桃av一区二区| 蜜桃av一区| 免费在线欧美视频| 免费在线观看一区二区三区| 亚洲一区二区三区高清| aa亚洲婷婷| 久久国产精品毛片| 亚洲一区国产| 蜜桃久久精品一区二区| 亚洲专区视频| 欧美日韩一区二区国产| 欧美一区二区三区久久| 国产精品久久久久毛片大屁完整版| 欧美日韩午夜电影网| 国产日韩在线观看视频| 美腿丝袜在线亚洲一区| 韩日一区二区| 日韩成人高清| 婷婷综合网站| 久热综合在线亚洲精品| 日本不卡不码高清免费观看| 日本久久二区| 国产精品欧美三级在线观看 | 国产一区2区| 日韩欧美网址| 免费av一区| 免费视频一区二区| 青草国产精品| 国产成人精品一区二区三区在线| 欧美sm一区| 亚洲主播在线| 久久国产日韩欧美精品| 精品一区二区三区视频在线播放| 高清久久精品| 欧美国产91| 免费观看在线综合色| 欧美日韩国产一区二区在线观看| 久久精品天堂| 伊人久久大香线蕉av不卡| 免费成人在线视频观看| 欧美天堂在线| av免费不卡国产观看| 欧美日韩国产在线一区| 日韩区一区二| 成人国产精品久久| 在线视频日韩| 国产精品乱战久久久| 日本久久成人网| 亚洲欧美日韩国产一区二区| 欧美日韩一区二区三区不卡视频 | 一区免费在线| 日韩精品亚洲一区二区三区免费| 卡一精品卡二卡三网站乱码| 99久久精品国产亚洲精品| 最新国产精品久久久| 久久国产麻豆精品| 久久精品不卡| 国产视频一区二| 久久精品青草| 91亚洲无吗| 免费在线小视频| 日韩亚洲精品在线观看| 亚洲美女久久精品| 亚洲欧美网站在线观看| 美女av在线免费看| 亚洲精品护士| 日韩免费av| 日本视频在线一区| 久久久久中文| 国产精品一区二区三区www| 香蕉成人av| 国产情侣久久| 91成人精品视频| 麻豆精品一区二区综合av| 欧美日韩精品一本二本三本| 国产精品porn| 国产亚洲一区在线| 欧美xxxx中国| 91精品丝袜国产高跟在线| 99久久精品网| 欧美aaaaaa午夜精品| 久久高清国产| 日韩伦理在线一区| 日本成人在线一区| 亚洲精品a级片| 国产精品99精品一区二区三区∴ | 久久久久国产精品一区二区| 日韩综合小视频| 国产一区二区中文|