首先來個前言
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
將像正常情況一樣經歷其所有生命周期-created
,mounted
等。//此處待驗證 生命周期是否重新執行了
不過,這並不是一個很好的解決方案,所以,讓我們做 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