做者:Michael Thiessen前端
譯者:前端小智vue
來源:hackernoongit
點贊再看,養成習慣github
本文
GitHub
github.com/qq449245884… 上已經收錄,更多往期高贊文章的分類,也整理了不少個人文檔,和教程資料。歡迎Star和完善,你們面試能夠參照考點複習,但願咱們一塊兒有點東西。面試
有時候,依賴 Vue 響應方式來更新數據是不夠的,相反,咱們須要手動從新渲染組件來更新數據。或者,咱們可能只想拋開當前的DOM,從新開始。那麼,如何讓Vue以正確的方式從新呈現組件呢?api
強制 Vue 從新渲染組件的最佳方法是在組件上設置:key
。 當咱們須要從新渲染組件時,只需更 key
的值,Vue 就會從新渲染組件。數組
這是一個很是簡單的解決方案。promise
固然,你可能會對其餘方式會更感興趣:工具
v-if
forceUpdate
方法key
更改這至關於每次你想關閉應用程序時都要從新啓動你的電腦。學習
這種方式或許有用,但這是一個很是糟糕的解決方案,不要這樣作,咱們來看看更好的方法。
v-if
v-if
指令,該指令僅在組件爲true
時才渲染。 若是爲false
,則該組件在DOM中不存在。
來看看,v-if
是怎麼工做的,在template
中,添加v-if
指令:
<template>
<my-component v-if="renderComponent" />
</template>
複製代碼
在script
中,使用nextTick
的方法
<script>
export default {
data() {
return {
renderComponent: true,
};
},
methods: {
forceRerender() {
// 從 DOM 中刪除 my-component 組件
this.renderComponent = false;
this.$nextTick(() => {
// 在 DOM 中添加 my-component 組件
this.renderComponent = true;
});
}
}
};
</script>
複製代碼
上面的過程大體以下:
剛開始 renderComponent
設置爲true
,所以渲染 my-component
組件
當咱們調用forceRerender
時,咱們當即將renderComponent
設置爲false
咱們中止渲染my-component
,由於v-if
指令如今計算結果爲false
在nextTick
方法中將renderComponent
設置回true
當v-if
指令的計算結果爲true
時,再次渲染my-component
在這個過程當中,有兩個部分比較重要
首先,咱們必須等到nextTick
,不然咱們不會看到任何變化。
在Vue中,一個 tick 是一個DOM更新週期。Vue將收集在同一 tick 中進行的全部更新,在 tick 結束時,它將根據這些更新來渲染 DOM 中的內容。若是咱們不等到next tick,咱們對renderComponent
的更新就會自動取消,什麼也不會改變。
其次,當咱們第二次渲染時,Vue將建立一個全新的組件。 Vue 將銷燬第一個,並建立一個新的,這意味着咱們的新my-component
將像正常狀況同樣經歷其全部生命週期-created
,mounted
等。
另外,nextTick
能夠與 promise 一塊兒使用:
forceRerender() {
// 從 DOM 中刪除 my-component 組件
this.renderComponent = false;
this.$nextTick().then(() => {
this.renderComponent = true;
});
}
複製代碼
不過,這並非一個很好的解決方案,因此,讓咱們作 Vue 想讓咱們作的
這是解決這個問題的兩種最佳方法之一,這兩種方法都獲得了Vue的官方支持。
一般狀況下,Vue 會經過更新視圖來響應依賴項中的更改。然而,當咱們調用forceUpdate
時,也能夠強制執行更新,即便全部依賴項實際上都沒有改變。
下面是大多數人使用這種方法時所犯的最大錯誤。
若是 Vue 在事情發生變化時自動更新,爲何咱們須要強制更新呢?
緣由是有時候 Vue 的響應系統會讓人感到困惑,咱們認爲Vue會對某個屬性或變量的變化作出響應,但實際上並非這樣。在某些狀況下,Vue的響應系統根本檢測不到任何變化。
因此就像上一個方法,若是你須要這個來從新渲染你的組件,可能有一個更好的方法。
有兩種不一樣的方法能夠在組件實例自己和全局調用forceUpdate
:
// 全局
import Vue from 'vue';
Vue.forceUpdate();
// 使用組件實例
export default {
methods: {
methodThatForcesUpdate() {
// ...
this.$forceUpdate();
// ...
}
}
}
複製代碼
重要提示:這不會更新任何計算屬性,調用forceUpdate
僅僅強制從新渲染視圖。
key
更改在許多狀況下,咱們須要從新渲染組件。
要正確地作到這一點,咱們將提供一個key
屬性,以便 Vue 知道特定的組件與特定的數據片斷相關聯。若是key
保持不變,則不會更改組件,可是若是key
發生更改,Vue 就會知道應該刪除舊組件並建立新組件。
正是咱們須要的!
可是首先,咱們須要繞一小段路來理解爲何在Vue中使用key
。
一旦你理解了這一點,那麼這是瞭解如何以正確方式強制從新渲染的很小的一步。
假設咱們要渲染具備如下一項或多項內容的組件列表:
有本地的狀態
某種初始化過程,一般在created
或mounted
鉤子中
經過jQuery或普通api進行無響應的DOM操做
若是你對該列表進行排序或以任何其餘方式對其進行更新,則須要從新渲染列表的某些部分。 可是,不會但願從新渲染列表中的全部內容,而只是從新渲染已更改的內容。
爲了幫助 Vue 跟蹤已更改和未更改的內容,咱們提供了一個key
屬性。 在這裏使用數組的索引,由於索引沒有綁定到列表中的特定對象。
const people = [
{ name: 'Evan', age: 34 },
{ name: 'Sarah', age: 98 },
{ name: 'James', age: 45 },
];
複製代碼
若是咱們使用索引將其渲染出來,則會獲得如下結果:
<ul>
<li v-for="(person, index) in people" :key="index">
{{ person.name }} - {{ index }}
</li>
</ul>
// Outputs
Evan - 0
Sarah - 1
James - 2
複製代碼
若是刪除Sarah
,獲得:
Evan - 0
James - 1
複製代碼
與James
關聯的索引被更改,即便James
仍然是James
。 James
會被從新渲染,這並非咱們但願的。
因此這裏,咱們可使用惟一的 id
來做爲 key
const people = [
{ id: 'this-is-an-id', name: 'Evan', age: 34 },
{ id: 'unique-id', name: 'Sarah', age: 98 },
{ id: 'another-unique-id', name: 'James', age: 45 },
];
<ul>
<li v-for="person in people" :key="person.id">
{{ person.name }} - {{ person.id }}
</li>
</ul>
複製代碼
在咱們從列表中刪除Sarah
以前,Vue刪除了Sarah
和James
的組件,而後爲James
建立了一個新組件。如今,Vue知道它能夠爲Evan
和James
保留這兩個組件,它所要作的就是刪除Sarah
的。
若是咱們向列表中添加一個person
,Vue 還知道能夠保留全部現有的組件,而且只須要建立一個新組件並將其插入正確的位置。這是很是有用的,當咱們有更復雜的組件,它們有本身的狀態,有初始化邏輯,或者作任何類型的DOM操做時,這對咱們頗有幫助。
因此接下來看看,若是使用最好的方法來從新渲染組件。
最後,這是強制Vue從新渲染組件的最佳方法(我認爲)。
咱們能夠採用這種將key
分配給子組件的策略,可是每次想從新渲染組件時,只需更新該key
便可。
這是一個很是基本的方法
<template>
<component-to-re-render :key="componentKey" />
</template>
export default {
data() {
return {
componentKey: 0,
};
},
methods: {
forceRerender() {
this.componentKey += 1;
}
}
}
複製代碼
每次forceRerender
被調用時,咱們的componentKey
都會改變。當這種狀況發生時,Vue將知道它必須銷燬組件並建立一個新組件。咱們獲得的是一個子組件,它將從新初始化自身並「重置」其狀態。
若是確實須要從新渲染某些內容,請選擇key
更改方法而不是其餘方法。
代碼部署後可能存在的BUG無法實時知道,過後爲了解決這些BUG,花了大量的時間進行log 調試,這邊順便給你們推薦一個好用的BUG監控工具 Fundebug。
原文:hackernoon.com/the-correct…
乾貨系列文章彙總以下,以爲不錯點個Star,歡迎 加羣 互相學習。
我是小智,公衆號「大遷世界」做者,對前端技術保持學習愛好者。我會常常分享本身所學所看的乾貨,在進階的路上,共勉!
關注公衆號,後臺回覆福利,便可看到福利,你懂的。