精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

從Javascript 事件循環看 Vue.nextTick 的原理和執行機制

開發 前端
Vue 的特點之一就是響應式,但是有些時候數據更新了,我們看到頁面上的 DOM 并沒有立刻更新。如果我們需要在 DOM 更新之后再執行一段代碼時,可以借助 nextTick 實現。

拋磚引玉

Vue 的特點之一就是響應式,但是有些時候數據更新了,我們看到頁面上的 DOM 并沒有立刻更新。如果我們需要在 DOM 更新之后再執行一段代碼時,可以借助 nextTick 實現。

[[323732]]

我們先來看一個例子

  1. export default { 
  2.   data() { 
  3.     return { 
  4.       msg: 0 
  5.     } 
  6.   }, 
  7.   mounted() { 
  8.     this.msg = 1 
  9.     this.msg = 2 
  10.     this.msg = 3 
  11.   }, 
  12.   watch: { 
  13.     msg() { 
  14.       console.log(this.msg) 
  15.     } 
  16.   } 

這里的結果是只輸出一個 3,而非依次輸出 1,2,3。這是為什么呢?

vue 的官方文檔是這樣解釋的:

Vue 異步執行 DOM 更新。只要觀察到數據變化,Vue 將開啟一個隊列,并緩沖在同一事件循環中發生的所有數據改變。如果同一個watcher 被多次觸發,只會被推入到隊列中一次。這種在緩沖時去除重復數據對于避免不必要的計算和 DOM 操作上非常重要。然后,在下一個的事件循環“tick”中,Vue 刷新隊列并執行實際 (已去重的) 工作。Vue 在內部嘗試對異步隊列使用原生的Promise.then和 MessageChannel,如果執行環境不支持,會采用setTimeout(fn, 0)代替。

假如有這樣一種情況,mounted鉤子函數下一個變量 a 的值會被++循環執行 1000 次。每次++時,都會根據響應式觸發setter->Dep->Watcher->update->run。如果這時候沒有異步更新視圖,那么每次++都會直接操作 DOM 一次,這是非常消耗性能的。所以 Vue 實現了一個queue隊列,在下一個 Tick(或者是當前 Tick 的微任務階段)的時候會統一執行queue中Watcher的run。同時,擁有相同 id 的Watcher不會被重復加入到該queue中去,所以不會執行 1000 次Watcher的run。最終的結果是直接把 a 的值從 1 變成 1000,大大提升了性能。

在 vue 中,數據監測都是通過Object.defineProperty來重寫里面的 set 和 get 方法實現的,vue 更新 DOM 是異步的,每當觀察到數據變化時,vue 就開始一個隊列,將同一事件循環內所有的數據變化緩存起來,等到下一次 eventLoop,將會把隊列清空,進行 DOM 更新。

想要了解 vue.nextTick 的執行機制,我們先來了解一下 javascript 的事件循環。

js 事件循環

js 的任務隊列分為同步任務和異步任務,所有的同步任務都是在主線程里執行的。異步任務可能會在 macrotask 或者 microtask 里面,異步任務進入 Event Table 并注冊函數。當指定的事情完成時,Event Table 會將這個函數移入 Event Queue。主線程內的任務執行完畢為空,會去 Event Queue 讀取對應的函數,進入主線程執行。上述過程會不斷重復,也就是常說的 Event Loop(事件循環)。

1. macro-task(宏任務):

每次執行棧執行的代碼就是一個宏任務(包括每次從事件隊列中獲取一個事件回調并放到執行棧中執行)。瀏覽器為了能夠使得 js 內部(macro)task與 DOM 任務能夠有序執行,會在一個(macro)task執行結束后,在下一個(macro)task執行開始前,對頁面進行重新渲染。宏任務主要包含:

  • script(整體代碼)
  • setTimeout / setInterval
  • setImmediate(Node.js 環境)
  • I/O
  • UI render
  • postMessage
  • MessageChannel

2. micro-task(微任務):

可以理解是在當前 task 執行結束后立即執行的任務。也就是說,在當前 task 任務后,下一個 task 之前,在渲染之前。所以它的響應速度相比 setTimeout(setTimeout 是 task)會更快,因為無需等渲染。也就是說,在某一個 macrotask 執行完后,就會將在它執行期間產生的所有 microtask 都執行完畢(在渲染前)。microtask 主要包含:

  • process.nextTick(Node.js 環境)
  • Promise
  • Async/Await
  • MutationObserver(html5 新特性)

3. 小結

  • 先執行主線程
  • 遇到宏隊列(macrotask)放到宏隊列(macrotask)
  • 遇到微隊列(microtask)放到微隊列(microtask)
  • 主線程執行完畢
  • 執行微隊列(microtask),微隊列(microtask)執行完畢
  • 執行一次宏隊列(macrotask)中的一個任務,執行完畢
  • 執行微隊列(microtask),執行完畢
  • 依次循環。。。

Vue.nextTick 源碼

vue 是采用雙向數據綁定的方法驅動數據更新的,雖然這樣能避免直接操作 DOM,提高了性能,但有時我們也不可避免需要操作 DOM,這時就該 Vue.nextTick(callback)出場了,它接受一個回調函數,在 DOM 更新完成后,這個回調函數就會被調用。不管是 vue.nextTick 還是vue.prototype.\$nextTick 都是直接用的nextTick這個閉包函數。

  1. export const nextTick = (function () { 
  2.   const callbacks = [] 
  3.   let pending = false 
  4.   let timerFunc 
  5.  
  6.   function nextTickHandler () { 
  7.     pending = false 
  8.     const copies = callbacks.slice(0) 
  9.     callbacks.length = 0 
  10.     for (let i = 0; i < copies.length; i++) { 
  11.       copies[i]() 
  12.     } 
  13.   } 
  14.  ... 
  15. })() 

使用數組callbacks保存回調函數,pending表示當前狀態,使用函數nextTickHandler 來執行回調隊列。在該方法內,先通過slice(0)保存了回調隊列的一個副本,通過設置 callbacks.length = 0清空回調隊列,最后使用循環執行在副本里的所有函數。

  1. if (typeof Promise !== 'undefined' && isNative(Promise)) { 
  2.   var p = Promise.resolve() 
  3.   var logError = err => { 
  4.     console.error(err) 
  5.   } 
  6.   timerFunc = () => { 
  7.     p.then(nextTickHandler).catch(logError) 
  8.     if (isIOS) setTimeout(noop) 
  9.   } 
  10. } else if (typeof MutationObserver !== 'undefined' && (isNative(MutationObserver) || MutationObserver.toString() === '[object MutationObserverConstructor]')) { 
  11.   var counter = 1 
  12.   var observer = new MutationObserver(nextTickHandler) 
  13.   var textNode = document.createTextNode(String(counter)) 
  14.   observer.observe(textNode, { 
  15.     characterData: true 
  16.   }) 
  17.   timerFunc = () => { 
  18.     counter = (counter + 1) % 2 
  19.     textNode.data = String(counter) 
  20.   } 
  21. } else { 
  22.   timeFunc = () => { 

隊列控制的最佳選擇是microtask,而microtask的最佳選擇是Promise。但如果當前環境不支持 Promise,就檢測到瀏覽器是否支持 MO,是則創建一個文本節點,監聽這個文本節點的改動事件,以此來觸發nextTickHandler(也就是 DOM 更新完畢回調)的執行。此外因為兼容性問題,vue 不得不做了microtask向macrotask 的降級方案。

為讓這個回調函數延遲執行,vue 優先用promise來實現,其次是 html5 的 MutationObserver,然后是setTimeout。前兩者屬于microtask,后一個屬于 macrotask。下面來看最后一部分。

  1. return function queueNextTick(cb?: Function, ctx?: Object) { 
  2.   let _resolve 
  3.   callbacks.push(() => { 
  4.     if (cb) cb.call(ctx) 
  5.     if (_resolve) _resolve(ctx) 
  6.   }) 
  7.   if (!pending) { 
  8.     pending = true 
  9.     timerFunc() 
  10.   } 
  11.   if (!cb && typeof Promise !== 'undefined') { 
  12.     return new Promise(resolve => { 
  13.       _resolve = resolve 
  14.     }) 
  15.   } 

這就是我們真正調用的nextTick函數,在一個event loop內它會將調用 nextTick的cb 回調函數都放入 callbacks 中,pending 用于判斷是否有隊列正在執行回調,例如有可能在 nextTick 中還有一個 nextTick,此時就應該屬于下一個循環了。最后幾行代碼是 promise 化,可以將 nextTick 按照 promise 方式去書寫(暫且用的較少)。

應用場景

場景一、點擊按鈕顯示原本以 v-show = false 隱藏起來的輸入框,并獲取焦點。

  1. <input id="keywords" v-if="showit"> 
  2.  
  3. showInput(){ 
  4.   this.showit = true 
  5.   document.getElementById("keywords").focus() 

以上的寫法在第一個 tick 里,因為獲取不到輸入框,自然也獲取不到焦點。如果我們改成以下的寫法,在 DOM 更新后就可以獲取到輸入框焦點了。

  1. showsou(){ 
  2.   this.showit = true 
  3.   this.$nextTick(function () { 
  4.     // DOM 更新了 
  5.     document.getElementById("keywords").focus() 
  6.   }) 

場景二、獲取元素屬,點擊獲取元素寬度。

  1. <div id="app"> 
  2.   <p ref="myWidth" v-if="showMe">{{ message }}</p> 
  3.   <button @click="getMyWidth">獲取p元素寬度</button> 
  4. </div> 
  5.  
  6. getMyWidth() { 
  7.   this.showMe = true
  8.   thisthis.message = this.$refs.myWidth.offsetWidth; 
  9.   //報錯 TypeError: this.$refs.myWidth is undefined 
  10.   this.$nextTick(()=>
  11.       //dom元素更新后執行,此時能拿到p元素的屬性 
  12.     thisthis.message = this.$refs.myWidth.offsetWidth; 
  13.   }) 

 

責任編輯:趙寧寧 來源: 前端先鋒隊
相關推薦

2020-09-21 14:35:20

VuenextTick前端

2017-09-12 09:50:08

JavaScriptEvent LoopVue.js

2017-02-09 15:15:54

Chrome瀏覽器

2024-08-26 14:52:58

JavaScript循環機制

2016-09-06 21:23:25

JavaScriptnode異步

2021-10-15 09:56:10

JavaScript異步編程

2020-12-29 08:21:03

JavaScript微任務宏任務

2010-07-16 09:00:20

開源RedOffice紅旗2000

2017-07-27 16:31:11

2015-09-21 14:20:35

2024-06-21 08:32:24

2021-01-18 08:24:51

JavaScriptMicrotask微任務

2024-09-20 05:46:00

2017-06-29 09:15:36

推薦算法策略

2022-04-25 09:03:16

JavaScript代碼

2009-03-17 15:36:29

JavaScript循環事件

2025-05-09 01:30:00

JavaScript事件循環基石

2021-12-08 07:55:41

EventLoop瀏覽器事件

2022-09-19 19:51:30

ReactuseEffect

2022-07-07 09:12:17

JavaScript線程循環機制
點贊
收藏

51CTO技術棧公眾號

永久免费看片视频教学| 亚洲日本理论电影| 国产黄色片免费看| 东京久久高清| 色综合久久综合| 中文字幕乱码一区二区三区| 高h震动喷水双性1v1| 久久午夜精品一区二区| 亚洲第一区第一页| 欧美视频在线观看视频| 免费播放片a高清在线观看| 久久一本综合频道| 欧美理论电影在线观看| 欧美熟妇一区二区| 欧美不卡在线观看| 又紧又大又爽精品一区二区| 精品一区二区三区国产| 亚洲天堂2021av| 一区二区国产在线观看| 久久亚洲国产精品| 久久发布国产伦子伦精品| 波多野结衣在线高清| 中文在线免费一区三区高中清不卡| 日韩av高清不卡| 日韩福利在线视频| 理论片一区二区在线| 欧美乱熟臀69xxxxxx| 国产日产欧美视频| 国产三级伦理在线| 亚洲色图制服诱惑| 国产精品一区视频| av小说天堂网| 麻豆国产欧美一区二区三区| 日本人成精品视频在线| 日操夜操天天操| 欧美午夜不卡影院在线观看完整版免费 | 日韩久久久久久久久久久久久| 成人av手机在线| 亚洲一区欧美激情| 国内精品久久久久影院 日本资源| 可以免费看av的网址| 自拍自偷一区二区三区| 欧美精品粉嫩高潮一区二区| 91av在线免费播放| 正在播放日韩精品| 欧美日韩国产限制| 高清在线观看免费| 亚洲风情在线资源| 色域天天综合网| 日日鲁鲁鲁夜夜爽爽狠狠视频97| a黄色在线观看| 国产午夜精品一区二区三区视频| 久久riav| 国产福利第一页| 国产专区欧美精品| 91久久精品国产91性色| 一区二区精品视频在线观看| 久久精品99国产精品| 国产精品自产拍在线观看中文| 欧美另类高清videos的特点| 麻豆专区一区二区三区四区五区| 欧美激情在线视频二区| 人人爽人人爽人人片| 一区二区网站| 欧美日韩国产美| 国产成人无码精品久久久性色| hd国产人妖ts另类视频| 成人欧美一区二区三区视频网页 | 午夜成人免费影院| 91麻豆.com| 99国产精品久久久久老师| 精品人妻一区二区三区含羞草| 国产精品一级黄| 国产一区视频在线播放| 国产乱淫片视频| 国产99精品国产| 亚洲精品欧美一区二区三区| 性中国xxx极品hd| 精品一区二区三区影院在线午夜| 欧美在线亚洲在线| 久久网中文字幕| 国产精品永久| 538国产精品一区二区在线| 欧美黑吊大战白妞| 亚洲一区黄色| 26uuu亚洲国产精品| 久久精品偷拍视频| 国产麻豆精品theporn| 国产美女久久精品香蕉69| 亚洲国产成人无码av在线| 精品69视频一区二区三区Q| 久久视频在线直播| 日本熟妇毛茸茸丰满| 肉色丝袜一区二区| 国产精品99久久99久久久二8| 国产精品特级毛片一区二区三区| 国产·精品毛片| 欧美高清视频一区| 你懂的视频在线观看| 91亚洲精品一区二区乱码| 亚洲成色www久久网站| 欧美aaaxxxx做受视频| 有码一区二区三区| 成人在线看视频| 二吊插入一穴一区二区| 狠狠操狠狠色综合网| 毛片在线播放视频| 超级白嫩亚洲国产第一| 欧美日韩一本到| 少妇一级淫免费放| 成人在线观看免费播放| 精品剧情v国产在线观看在线| 特黄特色免费视频| 成人羞羞视频播放网站| 中文字幕亚洲无线码在线一区| 免费一级特黄3大片视频| 第一会所亚洲原创| 久久精品国产精品| 麻豆chinese极品少妇| 日本欧美在线看| 成人信息集中地欧美| 国模精品一区二区| 欧美日韩国产色| 精人妻一区二区三区| 天堂美国久久| 久久久久久国产免费 | 欧美久久久久久蜜桃| 欧美性xxxx图片| 热久久天天拍国产| 欧美老肥婆性猛交视频| 在线观看免费中文字幕| 久久久美女毛片| 国产亚洲欧美在线视频| 国产精品久久久久久久久久白浆| 亚洲女人被黑人巨大进入| 久久人人爽人人爽人人| 久久资源在线| 免费久久99精品国产自| 美女日批视频在线观看| 91精品福利视频| 黄色国产在线观看| 91精品动漫在线观看| 国产男人精品视频| 成人资源www网在线最新版| 一区二区三区.www| 深夜福利网站在线观看| 奇米影视777在线欧美电影观看 | 亚洲精品成人a8198a| 草莓福利社区在线| 福利视频第一区| 成人亚洲免费视频| 久久婷婷蜜乳一本欲蜜臀| 久久久噜噜噜久久久| 国产成人精品a视频| 亚洲综合区在线| a级片在线观看视频| 亚洲日韩成人| 久久综合久久综合这里只有精品| 日本中文在线| 欧美性猛交xxxx乱大交| 内射中出日韩无国产剧情| 国产精品亚洲综合久久| 亚洲一区中文字幕| av免费在线免费观看| 精品久久五月天| 国产精品7777777| 久久午夜电影网| 午夜在线观看av| 亚洲澳门在线| 国产精品自产拍在线观| www红色一片_亚洲成a人片在线观看_| 色偷偷88欧美精品久久久| 伦伦影院午夜理论片| 狠狠爱成人网| 成人18视频| 欧美xxxhd| 国产亚洲aⅴaaaaaa毛片| 激情五月色婷婷| 成+人+亚洲+综合天堂| 国产高清精品在线观看| 成人在线免费视频观看| 91久久精品www人人做人人爽| 高清电影在线免费观看| 亚洲人成网站色ww在线| 日韩欧美成人一区二区三区| 国产女人水真多18毛片18精品视频| 夜夜夜夜夜夜操| 亚洲人体偷拍| 一区二区三区一级片| caoporn成人| 色与欲影视天天看综合网| 国产女人18毛片水18精| ●精品国产综合乱码久久久久| 国产吃瓜黑料一区二区| 久久精品欧洲| 日韩精品另类天天更新| 国产视频一区二| 日本一区二区在线免费播放| 国产美女av在线| 日韩精品在线观看网站| 伊人手机在线视频| 亚洲人成电影网站色mp4| 亚洲第一区第二区第三区| 亚洲人妖在线| 在线观看污视频| 国产欧美日韩精品一区二区三区 | 日韩免费高清| 好吊色欧美一区二区三区| 日韩亚洲国产免费| 久久综合电影一区| 精品国产区一区二| 亚洲午夜久久久久中文字幕久| 国产7777777| 国产综合久久久久久鬼色| 国产黄视频在线| 亚洲欧美在线专区| 国产一区二区三区免费不卡| 日韩第二十一页| 日韩免费中文字幕| 国模精品视频| 欧美精品videos性欧美| 亚洲日本在线播放| 717成人午夜免费福利电影| 国产性xxxx| youjizz久久| 亚洲精品一二三四| 狠狠色综合播放一区二区| 成人免费毛片播放| 一区二区三区导航| 2018日日夜夜| 国产亚洲精品美女久久久久久久久久| 国产91视觉| 毛片无码国产| 538国产精品一区二区免费视频 | 国产成人jvid在线播放| 涩涩视频在线播放| 中文字幕9999| 高h放荡受浪受bl| 日韩精品一区二区三区四区 | 性感美女一区二区在线观看| 69视频在线免费观看| av大全在线免费看| 精品久久国产97色综合| 中文字幕免费观看| 日韩欧美亚洲成人| 538精品在线观看| 伊人夜夜躁av伊人久久| 欧美三级小视频| 国产欧美一区二区三区在线看蜜臀 | 国产成人77亚洲精品www| 欧美黄色免费网站| 爱看av在线| 欧美xxxx做受欧美| 国产一区二区影视| 永久免费精品影视网站| 亚洲精品视频91| 欧美亚洲丝袜传媒另类| 日韩av一区二区在线播放| 亚洲一区电影777| 国产精品500部| 一区二区三区精品在线| 丁香激情五月少妇| 国产精品色婷婷久久58| 黄色片视频免费观看| 国产精品小仙女| 无码国产精品一区二区高潮| 秋霞午夜鲁丝一区二区老狼| 在线观看亚洲色图| 久热精品在线| 999这里有精品| 日韩精品一级二级| 在线观看免费视频高清游戏推荐| 一区二区福利| 日本欧美黄色片| 老司机精品久久| 在线播放黄色av| 99精品在线观看视频| 欧美xxxx日本和非洲| 91亚洲男人天堂| 一本色道综合久久欧美日韩精品| 久久精品夜夜夜夜久久| 精品黑人一区二区三区观看时间| 成人精品小蝌蚪| 少妇真人直播免费视频| 国产精品久99| 日韩黄色a级片| 婷婷久久综合九色国产成人 | 奇米精品在线| 欧美男gay| 国产尤物精品| 久久躁日日躁aaaaxxxx| 免费看电影在线| 欧美老女人性视频| 欧美三级精品| 国产第一区电影| 欧美香蕉视频| 国产国语videosex另类| 91精品福利观看| 亚洲free嫩bbb| 美女久久99| 日本精品一区二区三区不卡无字幕| 99久久夜色精品国产亚洲96| www.av中文字幕| 狠狠狠色丁香婷婷综合激情 | 日韩极品在线| 青草全福视在线| 日本色综合中文字幕| 婷婷免费在线观看| 久久99国产精品免费网站| 熟妇高潮精品一区二区三区| 亚洲嫩草精品久久| 久久久久无码国产精品| 欧美午夜一区二区三区| 日韩在线观看视频一区| xvideos亚洲| 日韩欧美一区二区三区免费观看| 国产精品美女免费看| 免费日韩成人| 鬼打鬼之黄金道士1992林正英| 日本一区二区在线看| 国产精品97在线| 成人免费视频caoporn| 精品无码久久久久成人漫画 | 国产后入清纯学生妹| 一区二区成人av| 综合图区亚洲| 国产原创欧美精品| 风间由美一区二区av101| 尤物国产精品| 美女脱光内衣内裤视频久久网站| 天天爽夜夜爽视频| 91一区二区三区在线观看| 九九热国产视频| 欧美日韩性生活| 国模人体一区二区| 一区二区国产精品视频| 高清不卡亚洲| yy111111少妇影院日韩夜片| 国产精品久久久乱弄| 特级黄色片视频| 亚洲欧美日韩小说| 国产区精品在线| 美女少妇精品视频| 精品一区二区三区亚洲| 欧美不卡福利| 欧美人成网站| 91人人澡人人爽| 国产精品入口麻豆原神| 中文字幕一区二区三区波野结| 中文精品99久久国产香蕉| 2020国产在线| 91免费在线视频| 欧美在线国产| youjizz.com国产| 欧美日韩色婷婷| 精品久久久久久亚洲综合网站| 欧美成人激情在线| 欧美日韩国产网站| 亚洲欧美精品在线观看| 精品在线亚洲视频| 欧美成欧美va| 欧美日韩在线播放| 五月激情丁香婷婷| 欧美成人亚洲成人日韩成人| 天堂久久午夜av| 亚洲一区二区三区精品在线观看 | 伊人网伊人影院| 欧美视频一区二区三区在线观看| 无套内谢的新婚少妇国语播放| 久久手机精品视频| 国产图片一区| 亚洲一二三区av| 久久精品一区二区| 国产免费不卡av| 色婷婷av一区二区三区在线观看| 天堂8中文在线最新版在线| 成人91免费视频| 午夜精品免费| 污污视频在线免费| 国产精品剧情在线亚洲| 国产女主播喷水视频在线观看 | 精品国产大片大片大片| 欧美大胆人体bbbb| 欧美gay囗交囗交| 日本道在线视频| 国产精品69久久久久水密桃 | 欧美性一二三区| 国产在线超碰| 国产不卡av在线免费观看| 色吊丝一区二区| 69堂免费视频| 91丨九色丨黑人外教| 影音先锋亚洲天堂| 日韩一区二区久久久| 日韩美女毛片| 制服下的诱惑暮生| 在线免费一区三区| 黄页在线观看免费| 制服诱惑一区| 国产尤物一区二区|