激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務(wù)器之家:專(zhuān)注于服務(wù)器技術(shù)及軟件下載分享
分類(lèi)導(dǎo)航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達(dá)式|C/C++|IOS|C#|Swift|Android|VB|R語(yǔ)言|JavaScript|易語(yǔ)言|vb.net|

服務(wù)器之家 - 編程語(yǔ)言 - 編程技術(shù) - 「源碼剖析」NextTick到底有什么作用

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

2021-02-02 23:15前端簡(jiǎn)報(bào)萌新小丑 編程技術(shù)

在vue中每次監(jiān)聽(tīng)到數(shù)據(jù)變化的時(shí)候,都會(huì)去調(diào)用notify通知依賴(lài)更新,觸發(fā)watcher中的update方法。

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

vue中每次監(jiān)聽(tīng)到數(shù)據(jù)變化的時(shí)候,都會(huì)去調(diào)用notify通知依賴(lài)更新,觸發(fā)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.  } 

如果通過(guò)watcher中的get方法去重新渲染組件,那么在渲染的過(guò)程中假如多次更新數(shù)據(jù)會(huì)導(dǎo)致同一個(gè)watcher被觸發(fā)多次,這樣會(huì)導(dǎo)致重復(fù)的數(shù)據(jù)計(jì)算和DOM的操作。如下圖所示,修改3次message之后DOM被操作了3次。

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

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

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

調(diào)用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隊(duì)列 
  17.  
  18. function resetSchedulerState () { 
  19.   index = queue.length  = 0 
  20.   has = {} 
  21.   waiting =  false 

在vue內(nèi)部調(diào)用nextTick(flushSchedulerQueue),vm.$nextTick方法調(diào)用的也是nextTick()方法

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

那么多次調(diào)用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將所有的回調(diào)函數(shù)暫存到了一個(gè)隊(duì)列中,然后通過(guò)異步調(diào)用更新去依次執(zhí)行隊(duì)列中的回調(diào)函數(shù)。

  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到底有什么作用

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

Promise

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

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

MutationObserver

MutationObserver 它會(huì)在指定的DOM發(fā)生變化時(shí)被調(diào)用。創(chuàng)建了一個(gè)文本DOM,通過(guò)監(jiān)聽(tīng)字符值的變化,當(dāng)文本字符發(fā)生變化的時(shí)候調(diào)用回調(diào)函數(shù)。

  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.   } 

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

setImmediate

setImmediate該方法用作把一些需要持續(xù)運(yùn)行的操作放在一個(gè)其他函數(shù)里,在瀏覽器完成后面的其他語(yǔ)句后,就立即執(zhí)行此替換函數(shù)。

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

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

總結(jié)

vue渲染DOM的時(shí)候觸發(fā)set方法中的去依賴(lài)更新,在更新的過(guò)程中watcher不是每次都去執(zhí)行去觸發(fā)DOM的更新,而是通過(guò)對(duì)wather的去重之后,通過(guò)nextTick異步調(diào)用觸發(fā)DOM更新。

nextTick()就是一個(gè)異步函數(shù),在異步函數(shù)中通過(guò)隊(duì)列批處理nextTick傳入的回調(diào)函數(shù)cb,但是隊(duì)列彼此不是同時(shí)進(jìn)行的,通過(guò)節(jié)流的方式依次執(zhí)行。

原文地址:https://mp.weixin.qq.com/s/UGk4-lOk0nLyCg5Pno1HQA

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 黄色免费在线网站 | 91免费影院 | 欧美一级aa免费毛片 | 西川av在线一区二区三区 | 91av在线国产 | 国产免费黄色 | 一级大黄毛片 | 欧美日韩中文字幕在线视频 | 国内免费视频成人精品 | 91精品国产日韩91久久久久久360 | 中文在线观看免费视频 | 一分钟免费观看完整版电影 | 乱淫67194| 欧美成人精品不卡视频在线观看 | 日韩精品一二三 | 蜜桃视频日韩 | 久久久aa | 斗罗破苍穹在线观看免费完整观看 | 久久精品79国产精品 | 久久精品一区二区三区不卡牛牛 | 手机av免费电影 | 国产va在线观看免费 | 色柚视频网站ww色 | 精品国产一区二区三区在线 | 久久精品亚洲一区二区 | 亚洲爱爱网站 | 国产做爰| 欧美人一级淫片a免费播放 久久99精品久久久久久园产越南 | 久久蜜桃精品一区二区三区综合网 | 鲁丝片一区二区三区免费入口 | 成年免费大片黄在线观看岛国 | 精品乱码久久久久 | 欧美激情天堂 | 亚洲影视在线 | 一级电影在线免费观看 | 爽毛片 | 天堂成人国产精品一区 | 最新中文字幕第一页视频 | 久久99精品国产99久久6男男 | 亚洲综人网 | 日美黄色片|