vue進階之強制組件渲染 大深坑


首先來個前言

原來Vue的dom更新是異步的,當數據發生變化,vue並不是里面去更新dom,而是開啟一個隊列。跟JavaScript原生的同步任務和異步任務相同。
Vue在一個同步任務過程中是不會去更新渲染視圖,而是在同步任務(事件循環隊列)執行完畢之后,在主線程的同步執行完畢,讀取任務隊列時更新視圖。
這個機制對於頁面性能是非常重要的,因為我們要是每操作一個數據就更新一次視圖,那么在性能上會非常差。而如果是在一次任務執行完畢之后更新視圖,可以避免特別多的重復操作。

1.在開發過程中,我們很容易遇見需要先渲染數據然后操作dom

這時候就要使用vue提供的nextTick函數。

這個函數就是有了數據之后,渲染完成之后會執行,也就是說當你需要數據先渲染,然后去操作渲染完成之后的dom,要把操作dom的邏輯寫在這個函數里面。

nextTick 可以與 promise 一起使用

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

//但是::只要我調用了  他就會執行  不管dom有沒有變化
forceRerender() {
  // 從 DOM 中刪除 my-component 組件
  this.renderComponent = false;

  this.$nextTick().then(() => {
    this.renderComponent = true;
  });
}

2.那么問題就來到了我們如何強制重新渲染dom

強制 Vue 重新渲染組件的最佳方法是在組件上設置:key。 當我們需要重新渲染組件時,只需更 key 的值,Vue 就會重新渲染組件。(這個方案存疑問  因為沒辦法檢測dom重新渲染了)

//此處待驗證 生命周期是否重新執行了

 

  • 簡單粗暴的方式:重新加載整個頁面
  • 不妥的方式:使用 v-if
  • 較好的方法:使用Vue的內置forceUpdate方法
  • 最好的方法:在組件上進行 key 更改

2.2現在看第二個方法

<template>
  <my-component v-if="renderComponent" />
</template>


<script>
  export default {
    data() {
      return {
        renderComponent: true,
      };
    },
    methods: {
      forceRerender() {
        // 從 DOM 中刪除 my-component 組件
        this.renderComponent = false;
        
        this.$nextTick(() => {
          // 在 DOM 中添加 my-component 組件
          this.renderComponent = true;
        });
      }
    }
  };
</script>

重點:首先,我們必須等到nextTick,否則我們不會看到任何變化

剛開始 renderComponent設置為true,因此渲染 my-component 組件
當我們調用forceRerender時,我們立即將renderComponent設置為false
我們停止渲染my-component,因為v-if指令現在計算結果為false
在nextTick方法中將renderComponent設置回true
當v-if指令的計算結果為true時,再次渲染my-component

在Vue中,一個 tick 是一個DOM更新周期。Vue將收集在同一 tick 中進行的所有更新,在 tick 結束時,它將根據這些更新來渲染 DOM 中的內容。如果我們不等到next tick,我們對renderComponent的更新就會自動取消,什么也不會改變。

其次,當我們第二次渲染時,Vue將創建一個全新的組件。 Vue 將銷毀第一個,並創建一個新的,這意味着我們的新my-component將像正常情況一樣經歷其所有生命周期-createdmounted等。//此處待驗證 生命周期是否重新執行了

不過,這並不是一個很好的解決方案,所以,讓我們做 Vue 想讓我們做的

2.3較好的方法:forceUpdate 方法

//官網
迫使 Vue 實例重新渲染。注意它僅僅影響實例本身和插入插槽內容的子組件,而不是所有子組件

Vue 會通過更新視圖來響應依賴項中的更改。然而,當我們調用forceUpdate時,也可以強制執行更新,即使所有依賴項實際上都沒有改變。

下面是大多數人使用這種方法時所犯的最大錯誤。

如果 Vue 在事情發生變化時自動更新,為什么我們需要強制更新呢?

原因是有時候 Vue 的響應系統會讓人感到困惑,我們認為Vue會對某個屬性或變量的變化做出響應,但實際上並不是這樣。在某些情況下,Vue的響應系統根本檢測不到任何變化。

所以就像上一個方法,如果你需要這個來重新渲染你的組件,可能有一個更好的方法。

有兩種不同的方法可以在組件實例本身和全局調用forceUpdate

// 全局
import Vue from 'vue';
Vue.forceUpdate();

// 使用組件實例
export default {
  methods: {
    methodThatForcesUpdate() {
      // ...
      this.$forceUpdate();
      // ...
    }
  }
}

重要提示:這不會更新任何計算屬性,調用forceUpdate僅僅強制重新渲染視圖。

2.4最好的方法:在組件上進行 key 更改

在許多情況下,我們需要重新渲染組件。

要正確地做到這一點,我們將提供一個key屬性,以便 Vue 知道特定的組件與特定的數據片段相關聯。如果key保持不變,則不會更改組件,但是如果key發生更改,Vue 就會知道應該刪除舊組件並創建新組件。

正是我們需要的!

但是首先,我們需要繞一小段路來理解為什么在Vue中使用key詳情

 

參考來源 

Vue異步更新視圖 https://www.jianshu.com/p/a1b0ed525f8e

Vue 中 強制組件重新渲染的正確方法 https://segmentfault.com/a/1190000021599461


免責聲明!

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



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