Vue動態路由快取不相互影響的解決辦法

雨天Rain發表於2019-02-18

這裡主要是想解決一個開發中的小問題:動態路由的快取,並且路由之間不會相互影響的問題。

先扯扯react與vue中都有的屬性key

之前在學習react的時候,常常遇到迴圈渲染元件時會提示需要在迴圈元件中加上key屬性,比如有一組列表:

import React, { Component } from 'react';

export default calss MainApp extends Component {
  state = {
    student: [
    {
      name: 'Jenny',
      id: 'a001'
    },
    {
      name: 'Jerry',
      id: 'a002'
    },
    ]
  }

  render() {
    return (
      <div>
          <ul>
          {
            this.state.student.map(item => {
              // key是必須的屬性,不然瀏覽器會丟擲錯誤提示
              return (<li key={item.id}>{item.name}</li>)	
            })
          }
          </ul>
        </div>
    )
  }
}
複製程式碼

可能對這個key不是太瞭解,或者也不許要太深入地去了解它,只知道在迴圈渲染元件時,隨手加上這個屬性就好。摘自網上的的文章的總結,key的作用為

key的作用主要是為了高效的更新虛擬DOM

雖然不是很懂,但也裝作大切大悟的樣子。key是一個給框架內部用的,我們只管給它加上去就好。

Vue也有的key

同樣有一個vue的元件:

<template>
  <div>
    <ul>
      <!-- key是必須的屬性,不然瀏覽器會丟擲錯誤提示 -->
      <li v-for="itme in student" :key={item.id}>{{item.name}}</li>
    </ul>
  </div>
</template>

<script>
import vue from 'vue';
import { Component } from 'vue-property-decorator'

@Component
export default calss MainApp extends vue {
  student = [
    {
      name: 'Jenny',
      id: 'a001'
    },
    {
      name: 'Jerry',
      id: 'a002'
    },
  ]
}
</script>
複製程式碼

同樣的,回到vue中的key,其實也類似,解釋key的作用,就不得不介紹一下虛擬DOM的diff演算法了...算了,我也不是很懂

簡單理解就是react與vue內部判斷元件的一個標識,用於更新或者重用元件的一個重要屬性

更新

key用於更新:是框架內部的演算法實現,一兩句話也說不清楚(主要是我也不懂這個演算法),簡單理解為當資料更新了,框架內部會判斷更新頁面哪些DOM元素需要更新刪除等操作;

重用

key用於元件重用:其實key不止是在map或者v-for中使用,我們也也可以在其他元件上使用這個屬性(至於哪個元件可以加,小孩子才做選擇,我們的目標是全都加!),當然加了貌似也沒什麼毛病,只是加了顯得有些多餘!

在做SPA的時候,我們都會有一個主元件App.vue:

<template>
  <div id="app">
    <div>
      <!-- keep-alive標籤會把路由快取下來 -->
      <keep-alive>
       	<router-view />
      </keep-alive>
    </div>
  </div>
</template>

<script>
import Vue from 'vue'
import { Component } from 'vue-property-decorator'

@Component
export default class MainApp extends Vue {
  
}
</script>
複製程式碼

上面程式碼會把頁面全部都快取下來(路由切換回來的時候,頁面表單填寫的內容沒有被清空),這是應為在<router-view />的外面包裹著keep-alive標籤, 頁面資料都保留下來了,避免使用者切換路由,資料丟失的情況,看似很完美!

比如一個產品頁面:

當兩個路由都使用同一個元件如Product.vue這個元件時,來回切換兩個路由,兩個頁面填寫的東西就會共用!切換頁面時,發現頁面自動填寫了上個頁面的東西,這並不是我們想要的!

如果頁面比較少, 比如只有A、B兩個產品,可以每個頁面都定義一個路由地址,並且name屬性不一樣的值:

{
  path: '/product',
  name: 'product',
  component: Product,
  children: [
    {
      path: 'a',
      name: 'aProduct',
      component: Detail
    },
   {
      path: 'b',
      name: 'bProduct',
      component: Detail
    },
  ]
}

複製程式碼

這時這樣<router-view :key="$route.name"/>就解決上面的問題了

But,頁面較多的時候,定義路由就不能像上面這樣定義了:

{
  path: '/product',
  name: 'product',
  component: Product,
  children: [
    {
      path: 'detail/:id',
      name: 'aProduct',
      component: Detail
    },
  ]
}

複製程式碼

此時路由變成了動態的了,那麼,key的值就不能取路由的name的值了,此時就需要引入一個變數來儲存路由的歷史記錄了,當路由切換時,在歷史記錄中匹配相應的路由,在歷史記錄中儲存的一個位置值,取出來賦值個key就可以了

嗯,前面好像廢話有點多,而且貌似有騙標題的嫌疑,其實理解key這個屬性,對於解決頁面快取,元件重複不相互影響有重要的作用。

如果有同學做類似的快取的時候,子路由遇到生命週期走裡多遍,也亦可能是key的原因,有時也是父元素使用v-if,但是具體問題具體分析

語言表達能力不好,就當給自己寫個筆記吧,哈哈

相關文章