成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

「源碼剖析」NextTick到底有什么作用

開發 前端
在vue中每次監聽到數據變化的時候,都會去調用notify通知依賴更新,觸發watcher中的update方法。

[[379888]]

 在vue中每次監聽到數據變化的時候,都會去調用notify通知依賴更新,觸發watcher中的update方法。

  1. update () { 
  2.    /* istanbul ignore else */ 
  3.    if (this.lazy) { 
  4.      
  5.    } else if (this.sync) { 
  6.    
  7.    } else { 
  8.      this.get() 
  9.      //queueWatcher(this) 
  10.    } 
  11.  } 

如果通過watcher中的get方法去重新渲染組件,那么在渲染的過程中假如多次更新數據會導致同一個watcher被觸發多次,這樣會導致重復的數據計算和DOM的操作。如下圖所示,修改3次message之后DOM被操作了3次。


為了解決上述問題,不去直接調用get方法而是將每次調用update方法后需要批處理的wather暫存到一個隊列當中,如果同一個 watcher 被多次觸發,通過wacther 的id屬性對其去重,只會被推入到隊列中一次。然后,等待所有的同步代碼執行完畢之后在下一個的事件循環中,Vue 刷新隊列并執行實際 (已去重的) 工作。

  1. let has: { [key: number]: ?true } = {} 
  2. let waiting = false 
  3. export function queueWatcher (watcher: Watcher) { 
  4.   const id = watcher.id  //對watcher去重 
  5.   if (has[id] == null) { 
  6.     has[id] = true 
  7.     queue.push(watcher); 
  8.     if (!waiting) {  //節流 
  9.       waiting = true 
  10.       nextTick(flushSchedulerQueue) 
  11.     } 

調用watcher的run方法異步更新DOM

  1. let has: { [key: number]: ?true } = {} 
  2. function flushSchedulerQueue () { 
  3.   let watcher, id 
  4.   queue.sort((a, b) => a.id - b.id) 
  5.  
  6.   for (index = 0; index < queue.length; index++) { 
  7.     watcher = queue[index
  8.     if (watcher.before) { 
  9.       watcher.before() 
  10.     } 
  11.     id = watcher.id 
  12.     has[id] = null  //清空id 
  13.     watcher.run()   //更新值 
  14.   } 
  15.    
  16.   resetSchedulerState()   //清空watcher隊列 
  17.  
  18. function resetSchedulerState () { 
  19.   index = queue.length  = 0 
  20.   has = {} 
  21.   waiting =  false 

在vue內部調用nextTick(flushSchedulerQueue),vm.$nextTick方法調用的也是nextTick()方法

  1. Vue.prototype.$nextTick = function (cb) { 
  2.    nextTick(cb,this); 
  3.  }; 

那么多次調用nextTick方法是怎么處理的呢?

  1. const callbacks = [] 
  2. let pending = false  
  3. export function nextTick (cb?: Function, ctx?: Object) { 
  4.   callbacks.push(() => { 
  5.     if (cb) { 
  6.       try { 
  7.         cb.call(ctx) 
  8.       } catch (e) { 
  9.         handleError(e, ctx, 'nextTick'
  10.       } 
  11.     } 
  12.   }) 
  13.   if (!pending) { 
  14.     pending = true 
  15.     timerFunc() 
  16.   } 

nextTick將所有的回調函數暫存到了一個隊列中,然后通過異步調用更新去依次執行隊列中的回調函數。

  1. function flushCallbacks () { 
  2.   pending = false 
  3.   const copies = callbacks.slice(0) 
  4.   callbacks.length = 0 
  5.   for (let i = 0; i < copies.length; i++) { 
  6.     copies[i]() 
  7.   } 

 

nextTick函數中異步更新對兼容性做了處理,使用原生的 Promise.then、MutationObserver 和 setImmediate,如果執行環境不支持,則會采用 setTimeout(fn, 0) 代替。

Promise

  1. if (typeof Promise !== 'undefined' && isNative(Promise)) { 
  2.   const p = Promise.resolve() 
  3.   timerFunc = () => { 
  4.     p.then(flushCallbacks) 
  5.   } 

 

MutationObserver

MutationObserver 它會在指定的DOM發生變化時被調用。創建了一個文本DOM,通過監聽字符值的變化,當文本字符發生變化的時候調用回調函數。

  1. if (!isIE && typeof MutationObserver !== 'undefined' && ( 
  2.   isNative(MutationObserver) || 
  3.   MutationObserver.toString() === '[object MutationObserverConstructor]' 
  4. )) { 
  5.   let counter = 1 
  6.   const observer = new MutationObserver(flushCallbacks) 
  7.   const textNode = document.createTextNode(String(counter)) 
  8.   observer.observe(textNode, { 
  9.     characterData: true 
  10.   }) 
  11.   timerFunc = () => { 
  12.     counter = (counter + 1) % 2 
  13.     textNode.data = String(counter) 
  14.   } 

 

setImmediate

setImmediate該方法用作把一些需要持續運行的操作放在一個其他函數里,在瀏覽器完成后面的其他語句后,就立即執行此替換函數。

  1. if (typeof setImmediate !== 'undefined' && isNative(setImmediate)) { 
  2.   timerFunc = () => { 
  3.     setImmediate(flushCallbacks) 
  4.   } 
  5. }else
  6.   timerFunc = () => { 
  7.     setTimeout(flushCallbacks, 0) 
  8.   } 

 

總結

vue渲染DOM的時候觸發set方法中的去依賴更新,在更新的過程中watcher不是每次都去執行去觸發DOM的更新,而是通過對wather的去重之后,通過nextTick異步調用觸發DOM更新。

nextTick()就是一個異步函數,在異步函數中通過隊列批處理nextTick傳入的回調函數cb,但是隊列彼此不是同時進行的,通過節流的方式依次執行。

 

責任編輯:姜華 來源: 前端簡報
相關推薦

2024-10-15 09:48:56

2018-06-26 14:29:44

LinuxUnix不同

2024-02-26 07:36:09

lockJava語言

2022-09-14 09:45:15

指標標簽

2012-07-25 15:45:28

ERPSCM

2019-10-14 10:09:33

Wi-Fi 6Wi-Fi無線網絡

2021-09-06 10:45:18

XDRMDR

2016-09-22 16:47:55

iOSAndroidWindows Pho

2022-09-01 21:02:31

手機衛星5G

2018-08-13 07:32:42

物聯網聯網物IOT

2019-06-25 09:49:01

5G承載網網絡

2020-02-27 08:52:51

NFVSDN網絡

2020-10-20 09:57:04

量子計算人工智能技術

2021-03-09 05:49:32

通信女性從業者通信行業

2012-05-31 09:24:55

云計算云存儲

2020-08-05 07:00:00

SSD硬盤存儲

2022-09-27 09:43:08

物聯網設備物聯網

2022-07-29 08:25:02

volatileC語言原子

2022-10-27 19:32:20

切片golang數組

2011-06-22 17:18:13

外鏈
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 性高湖久久久久久久久 | 亚洲第一网站 | 手机日韩 | 黄色网毛片 | 亚洲三级国产 | 国产美女自拍视频 | 日韩av免费在线电影 | 国产视频久 | 神马久久av| 91av免费看 | 国产一二三区电影 | 成人不卡 | 天天操天天操 | 婷婷激情综合 | 丁香五月网久久综合 | 久久99精品国产 | 一区二区福利视频 | 欧美爱爱视频 | 天天拍天天插 | 国产99久久精品一区二区永久免费 | 亚洲+变态+欧美+另类+精品 | 嫩草最新网址 | 欧美一区二区三区国产 | 91久久久久久久久 | 欧美人妇做爰xxxⅹ性高电影 | 日中文字幕在线 | 欧美三区 | 亚洲综合一区二区三区 | 亚洲h视频 | 天堂视频免费 | 免费在线看黄 | 欧美综合一区二区三区 | 国产高清精品一区二区三区 | 免费av在线网站 | 精品av| 99热首页 | 羞羞视频在线观看 | av高清毛片| 一级网站| 男人天堂99 | 91视频正在播放 |