很多人不知道可以使用這種 Key 的方式來(lái)對(duì) Vue 組件進(jìn)行重新渲染!
在某些情況下,我們必須強(qiáng)制Vue重新渲染組件,如果沒(méi)有,那可能,你做的業(yè)務(wù)還不夠負(fù)責(zé),反正我是經(jīng)常需要重新渲染組件,哈哈。
雖然Vue不會(huì)自動(dòng)更新這種情況是相對(duì)比較少,但是知道如何在出現(xiàn)這個(gè)問(wèn)題時(shí)修復(fù)它還是很有用的。
在大多數(shù)情況下,此問(wèn)題根源還是我們對(duì) Vue 的響應(yīng)式理解還是不夠到位。因此,要盡量確保我們要正確使用了Vue。響應(yīng)式有時(shí)過(guò)于棘手,我也經(jīng)常不知道所措。
這節(jié),我們就來(lái)做一些之前很少做過(guò)或者沒(méi)做過(guò)的:用 key 來(lái)讓組件重新渲染。
在這篇文章中,會(huì)涉及到這幾個(gè)知識(shí)點(diǎn):
- key 是如何改變組件
 - key 如何與多個(gè)子組件一起工作
 - 如何強(qiáng)制子組件自己更新
 
通過(guò)改變 key 的值來(lái)重新渲染組件
我最喜歡的方法是使用key屬性,因?yàn)槭褂胟ey 的方式,Vue 就知道了特定組件與特定數(shù)據(jù)相關(guān)。
如果 key保持不變,則不會(huì)更改組件。但是,如果key發(fā)生更改, Vue 知道它應(yīng)該刪除舊組件并創(chuàng)建一個(gè)新組件。
下面是一個(gè)非常基本的方法:
- <template>
 - <ComponentToReRender
 - :key="componentKey"
 - />
 - </template>
 - <script>
 - export default {
 - data() {
 - return {
 - componentKey: 0,
 - };
 - },
 - methods: {
 - forceRerender() {
 - this.componentKey += 1;
 - }
 - }
 - }
 - </script>
 
每次調(diào)用forceRerender時(shí),componentKey 的值就會(huì)更改。當(dāng)componentKey 的值發(fā)生改變時(shí),Vue 就知道把ComponentToReRender組件刪除并創(chuàng)建一個(gè)新組件。
這樣ComponentToReRender就會(huì)重新渲染并重置里面的狀態(tài)。nice nice!
強(qiáng)制多個(gè)子節(jié)點(diǎn)進(jìn)行更新
同樣用這種方式也可以用于多個(gè)子組件:
- <template>
 - <div>
 - <Child
 - :key="key1"
 - />
 - <Child
 - :key="key2"
 - />
 - </div>
 - </template>
 - <script>
 - export default {
 - data() {
 - return {
 - key1: 0,
 - key2: 0,
 - };
 - },
 - methods: {
 - forceRerender(child) {
 - if (child === 1) {
 - this.key1 += 1;
 - } else if( child === 2) {
 - this.key2 += 1;
 - }
 - }
 - }
 - }
 - </script>
 
這里我們使用了兩個(gè)單獨(dú) key 來(lái)分別控制每個(gè)子組件是否重新渲染。將它們分開(kāi)是為了其中的一個(gè)子組件渲染,不會(huì)影響到另外另一個(gè)。
但如果希望兩個(gè)子組件總是一起更新,則可以使用相同的 kye。但是,key必須是唯一的,所以下面這種方式,不能工作:
- <template>
 - <div>
 - <Child
 - :key="componentKey"
 - />
 - <Child
 - :key="componentKey"
 - />
 - </div>
 - </template>
 - <script>
 - export default {
 - data() {
 - return {
 - componentKey: 0,
 - };
 - },
 - methods: {
 - forceRerender(child) {
 - this.componentKey += 1;
 - }
 - }
 - }
 - </script>
 
在這里,僅第一個(gè)Child組件會(huì)被渲染。第二個(gè)被忽略,因?yàn)樗哂兄貜?fù)的key 了。
為了解決這個(gè)問(wèn)題,我們可以基于componentKey為每個(gè)孩子構(gòu)造一個(gè)新key:
- <template>
 - <div>
 - <Child
 - :key="`${componentKey}-1`"
 - />
 - <Child
 - :key="`${componentKey}-2`"
 - />
 - </div>
 - </template>
 - <script>
 - export default {
 - data() {
 - return {
 - componentKey: 0,
 - };
 - },
 - methods: {
 - forceRerender(child) {
 - this.componentKey += 1;
 - }
 - }
 - }
 - </script>
 
因?yàn)槲覀兠看卧赾omponentKey后面添加-1和-2,所以這兩個(gè)key始終是唯一的,現(xiàn)在這兩個(gè)組件都將被重新渲染。
如果是在列表中,則可以使用如下方式:
- <template>
 - <div>
 - <Child
 - v-for="(item, index) in list"
 - :key="`${componentKey}-${index}`"
 - />
 - </div>
 - </template>
 - <script>
 - export default {
 - data() {
 - return {
 - list: [
 - // ...
 - ],
 - componentKey: 0,
 - };
 - },
 - methods: {
 - forceRerender(child) {
 - this.componentKey += 1;
 - }
 - }
 - }
 - </script>
 
在這里,我們將key構(gòu)造為${componentKey}-${index},因此列表中的每個(gè)項(xiàng)目都會(huì)獲得唯一的key,只要componentKey一改變,列表中的所有組件將同時(shí)重新渲染。
當(dāng)然,還有更簡(jiǎn)單的方式,就是用div把列表包裹起來(lái),直接對(duì) div重新更新就行了:
- <template>
 - <div :key="componentKey">
 - <Child
 - v-for="item in list"
 - :key="item.id"
 - />
 - </div>
 - </template>
 - <script>
 - export default {
 - data() {
 - return {
 - list: [
 - // ...
 - ],
 - componentKey: 0,
 - };
 - },
 - methods: {
 - forceRerender(child) {
 - this.componentKey += 1;
 - }
 - }
 - }
 - </script>
 
這中思路可以用在很多地方,可以為我們擺脫很的困境,大家要牢記起來(lái)。
好了,今天就跟大家分享到這里,我們下期在見(jiàn),謝謝大家的觀看。
作者:Michael Thiessen 譯者:前端小智 來(lái)源:medium
原文:https://morioh.com/p/08963bf07353
本文轉(zhuǎn)載自微信公眾號(hào)「大遷世界」,可以通過(guò)以下二維碼關(guān)注。轉(zhuǎn)載本文請(qǐng)聯(lián)系大遷世界公眾號(hào)。
















 
 
 










 
 
 
 