this.$nextTick()的原理與使用場景


遇到這個方法的時候,比較困惑,搜集一些資料,總結一下其原理和用途

 

官網說法:在下次 DOM 更新循環結束之后執行延遲回調。在修改數據之后立即使用這個方法,獲取更新后的 DOM。

獲取更新后的DOM,言外之意就是什么操作需要用到了更新后的DOM,
而不能使用之前的DOM,
所以就衍生出了這個獲取更新后的 DOM的Vue方法

DOM是如何更新的呢?

 

1.原理

Vue實現響應式並不是數據發生變化之后DOM立即變化,而是異步執行DOM更新的。

異步執行的運行機制是什么樣的?阮一峰老師是這樣總結的:

(1)所有同步任務都在主線程上執行,形成一個執行棧(execution context stack)。

(2)主線程之外,還存在一個"任務隊列"(task queue)。只要異步任務有了運行結果,就在"任務隊列"之中放置一個事件。

(3)一旦"執行棧"中的所有同步任務執行完畢,系統就會讀取"任務隊列",看看里面有哪些事件。那些對應的異步任務,於是結束等待狀態,進入執行棧,開始執行。

(4)主線程不斷重復上面的第三步。

主線程不斷執行任務、獲取任務、執行任務……的過程叫做事件循環

vue異步更新的原理:

1.修改 Vue 中的 Data 時,就會觸發所有和這個 Data 相關的 Watcher 進行更新。

2.首先,會將所有的 Watcher 加入隊列 Queue。

3.然后,調用 nextTick 方法,執行異步任務。

4.在異步任務的回調中,對 Queue 中的 Watcher 進行排序,然后執行對應的 DOM 更新。

// 當一個 Data 更新時,會依次執行以下代碼
// 1. 觸發 Data.set
// 2. 調用 dep.notify 訂閱者
// 3. Dep 會遍歷所有相關的 Watcher 執行 update 方法
class Watcher {
  // 4. 執行更新操作
  update() {
    queueWatcher(this);
  }
}

const queue = [];

function queueWatcher(watcher: Watcher) {
  // 5. 將當前 Watcher 添加到異步隊列
  queue.push(watcher);
  // 6. 執行異步隊列,並傳入回調
  nextTick(flushSchedulerQueue);
}

// 更新視圖的具體方法
function flushSchedulerQueue() {
  let watcher, id;
  // 排序,先渲染父節點,再渲染子節點
  // 這樣可以避免不必要的子節點渲染,如:父節點中 v-if 為 false 的子節點,就不用渲染了
  queue.sort((a, b) => a.id - b.id);
  // 遍歷所有 Watcher 進行批量更新。
  for (index = 0; index < queue.length; index++) {
    watcher = queue[index];
    // 更新 DOM
    watcher.run();
  }
}

2.this.$nextTick()的使用場景

什么時候需要用Vue.nextTick():

  1. 在Vue生命周期的created()鈎子函數進行的DOM操作一定要放在Vue.nextTick()的回調函數中。原因是在created()鈎子函數執行的時候DOM 其實並未進行任何渲染,而此時進行DOM操作無異於徒勞,所以此處一定要將DOM操作的js代碼放進Vue.nextTick()的回調函數中。與之對應的就是mounted鈎子函數,因為該鈎子函數執行時所有的DOM掛載和渲染都已完成,此時在該鈎子函數中進行任何DOM操作都不會有問題 。
  2. 在數據變化后要執行的某個操作,當你設置 vm.someData = ‘new value’,DOM並不會馬上更新,而是在異步隊列被清除,也就是下一個事件循環開始時執行更新時才會進行必要的DOM更新。如果此時你想要根據更新的 DOM 狀態去做某些事情,就會出現問題。。為了在數據變化之后等待 Vue 完成更新 DOM ,可以在數據變化之后立即使用 Vue.nextTick(callback) 。這樣回調函數在 DOM 更新完成后就會調用。
  3. mounted 不會承諾所有的子組件也都一起被掛載。如果你希望等到整個視圖都渲染完畢,可以用 vm.$nextTick 替換掉 mounted

 

參考---https://www.icode9.com/content-4-816250.html

參考---https://www.jianshu.com/p/46c9d777cab1

參考---https://www.cnblogs.com/pleaseAnswer/p/13566987.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM