国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

VueJS源碼學習——MutationObserver實現nextTick

xumenger / 2767人閱讀

摘要:倡導開發者盡量不直接操作,但有的時候由于各種需求讓開發者不得不這樣做,于是的實現就是讓開發者在修改數據后,能夠在數據更新到后才執行對應的函數,從而獲取最新的數據。

Vue 倡導開發者盡量不直接操作 DOM,但有的時候由于各種需求讓開發者不得不這樣做,于是 nextTick 的實現就是讓開發者在修改數據后,能夠在數據更新到 DOM 后才執行對應的函數,從而獲取最新的 DON 數據。

原文地址
項目地址

那么如何實現 nextTick呢,我們首先可以想到的是利用 setTimeout 的異步回調來實現,不過由于各個瀏覽器的不同,setTimeout 的延遲很高,因此在 nextTick 中只作為最后的備胎,首選的方案則是 MutationObserver(在后面的內容中 MO 代表 MutationObserver)

nextTick 的源碼實現
export const nextTick = (function () {
  var callbacks = []
  var pending = false
  var timerFunc
  function nextTickHandler () {
    pending = false
    var copies = callbacks.slice(0)
    callbacks = []
    for (var i = 0; i < copies.length; i++) {
      copies[i]()
    }
  }
  /* istanbul ignore if */
  if (typeof MutationObserver !== "undefined") { // 首選 MutationObserver 
    var counter = 1
    var observer = new MutationObserver(nextTickHandler) // 聲明 MO 和回調函數
    var textNode = document.createTextNode(counter)
    observer.observe(textNode, { // 監聽 textNode 這個文本節點
      characterData: true // 一旦文本改變則觸發回調函數 nextTickHandler
    })
    timerFunc = function () {
      counter = (counter + 1) % 2 // 每次執行 timeFunc 都會讓文本在 1 和 0 間切換
      textNode.data = counter
    }
  } else {
    timerFunc = setTimeout // 如果不支持 MutationObserver, 退選 setTimeout
  }
  return function (cb, ctx) {
    var func = ctx
      ? function () { cb.call(ctx) }
      : cb
    callbacks.push(func)
    if (pending) return
    pending = true
    timerFunc(nextTickHandler, 0)
  }
})()
MutationObserver 的功能和作用

MO 給開發者提供了一種能在某個范圍內的DOM數發生變化時作出適當反應的能力 ——MDN

用人話說是開發者能通過它創建一個觀察者對象,這個對象會監聽某個DOM元素,并在它的DOM樹發生變化時執行我們提供的回調函數。

具體參考這個 DEMO

比較特別的是實例化的時候需要先傳入回調函數:

var observer = new MutationObserver(function(mutations) {
  mutations.forEach(function(mutation) {
    console.log(mutation.type);
  })
})

然后才配置觀察選項,包括觀察節點和觀察的屬性:

// 選擇目標節點
var target = document.querySelector("#some-id");
 
// 配置觀察選項:
var config = { attributes: true, childList: true, characterData: true }
 
// 傳入目標節點和觀察選項
observer.observe(target, config);
 
// 隨后,你還可以停止觀察
observer.disconnect();

對于老版本的谷歌和火狐,則需要使用帶前綴的 MO:

var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver
MutationObserver 和 microtask

那么為什么優選使用 MutationObserver呢?

一開始以為是 MO 就是用來監聽 DOM 變化的,那么使用 textnode 模擬 DOM 變化再利用 MO 來監聽觸發從而實現 nextTick 不就很適合,直到了解看到了知乎上的問答才知道是因為 MO 會比 setTimeout 早執行的緣故,

這里需要了解JS的運行運行機制(重新刷新了我的三觀), JS 的事件運行機制執行的時候會區分 taskmicrotask, 引擎在每個 task 執行完畢,并在從隊列里取下一個task來執行之前, 執行完所有的 microtask 隊列中的 microtask


(task 和 microtask 摘自 https://jakearchibald.com/)

setTimeout 回調會被分配到一個新的task中等待執行,而 Promise 的 resolver、MO 的 回調都會被分配到 microtask 的隊列中,所以會比 setTimout 先執行

除了比 setTimout 快之外,還有 渲染性能 的問題,根據HTML Standard, 每個 task 運行完以后, UI 都會重新渲染,那么在 microtask 中就完成數據更新, 當前 task 結束就可以得到最新的 UI, 反之如果新建一個 task 來做數據更新,那么渲染就會進行兩次。

所以性價比如此高的 MO 自然成為了首選

關于 microtask,具體可以閱讀 Jake 寫的 Tasks, microtasks, queues and schedules

nextTick 的版本迭代

上面關于 nextTick 的源碼實現屬于 vue 最早的版本 v1.0.9,在深挖 mutationObserver 的時候發現 nextTick 在vue的版本迭代中也在不斷的進化,同事也發生過退化,非常有趣:

先說說退化的事件,尤大(vue的作者)曾經使用 window.postMessage 來替代 MO 實現 nextTick,結果開發者使用后發現了問題,可以看看這兩個 JSFiddle:jsfiddle1 和 jsfiddle2, 兩個例子用了不同版本來實現元素的絕對定位,第一個使用的是 2.0.0-rc6,這個版本采用的是 MO,而后來因為 IOS 9.3 的 WebView 里 MO 有 bug,尤大便換成 window.postMessage來實現,即第二個實例版本為 2.0.0-rc7, 但是由于 postMessage 會將回調放到 macrotask 其實也就是 task 里面,導致可能執行了多次 UI 的task都沒有執行 window.postMessage 的 task,也就延遲了更新DOM操作的時間。尤大在后續版本撤回了這一次修改,具體的討論可以看issue

關于進化,在后續的版本里,由于 es6 的新語法,nextTick 開始使用 Promise.then 和 MO 來做首選和次選,在前面的討論中已經提到,Promise.then 也屬于 microtask。

資源

MutationObserver MDN

Tasks, microtasks, queues and schedules

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/88447.html

相關文章

  • VueJS源碼學習——元素在插入和移出 dom 時的過渡邏輯

    摘要:原文地址項目地址關于中使用效果,官網上的解釋如下當元素插入到樹或者從樹中移除的時候,屬性提供變換的效果,可以使用來定義變化效果,也可以使用來定義首先第一個函數是將元素插入,函數實現調用了實現代碼如下寫的好的代碼就是文檔,從注釋和命名上就 src/transition 原文地址項目地址 關于 vue 中使用 transition 效果,官網上的解釋如下: With Vue.js’ tra...

    Dogee 評論0 收藏0
  • VueJS源碼學習——工具類函數實現(二)

    摘要:它被當做一個輕量版本的使用,用于存儲已排好版的或尚未打理好格式的片段。最大的區別是因為不是真實樹的其中一部分,它的變化不會引起樹的重新渲染的操作,或者導致性能影響的問題出現。 原文地址項目地址 工具類 /** * Simple bind, faster than native * * @param {Function} fn * @param {Object} ctx * @...

    fish 評論0 收藏0
  • 從Vue.js源碼看異步更新DOM策略及nextTick

    摘要:我們發現默認是使用異步執行更新。優先使用,在不存在的情況下使用,這兩個方法的回調函數都會在中執行,它們會比更早執行,所以優先使用。是最后的一種備選方案,它會將回調函數加入中,等到執行。 寫在前面 因為對Vue.js很感興趣,而且平時工作的技術棧也是Vue.js,這幾個月花了些時間研究學習了一下Vue.js源碼,并做了總結與輸出。文章的原地址:https://github.com/ans...

    leo108 評論0 收藏0
  • Vue.nextTick使用和源碼分析

    摘要:而中的回調函數則會在頁面渲染后才執行。還使用方法復制數組并把數組清空,這里的數組就是存放主線程執行過程中的函數所傳的回調函數集合主線程可能會多次使用方法。到這里就已經實現了根據環境選擇異步方法,并在異步方法中依次調用傳入方法的回調函數。 Vue.nextTick的應用場景 Vue 是采用異步的方式執行 DOM 更新。只要觀察到數據變化,Vue 將開啟一個隊列,并緩沖同一事件循環中發生的...

    Jrain 評論0 收藏0
  • 【Vue源碼】Vue中DOM的異步更新策略以及nextTick機制

    摘要:本篇文章主要是對中的異步更新策略和機制的解析,需要讀者有一定的使用經驗并且熟悉掌握事件循環模型。這個結果足以說明中的更新并非同步。二是把回調函數放入一個隊列,等待適當的時機執行。通過的主動來觸發的事件,進而把回調函數作為參與事件循環。 本篇文章主要是對Vue中的DOM異步更新策略和nextTick機制的解析,需要讀者有一定的Vue使用經驗并且熟悉掌握JavaScript事件循環模型。 ...

    selfimpr 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<