Copyright © 2008 ~ 2024 MUKI space* / omegaBook theme All Rights Reserved.

情境

以切換使用者為例,如果我們切換了使用者,所有的權限、資料,與能看到的畫面都會有所不同。所以會從生命週期 onMounted 開始,重新撈取 API 與其相關元件資料,然後再更新給新的使用者。

而我覺得比較好的體驗,是提供 Loading 畫面,並在背景更新完後渲染資料,不需要重新整理頁面 (window.reload)

搭配 Vue3 和虛擬 DOM 機制

實作這個功能前,我們先來了解一下 Vue3 他是如何渲染路由的?以及他是如何使用虛擬 DOM 的。

什麼是虛擬 DOM

虛擬 DOM 最早是由 React.js 提出,是一種可以在網頁開發中提高效能的技術。他模擬了實際 DOM 樹狀結構,並存於記憶體中。

虛擬 DOM 運作原理

  1. 建立虛擬的 DOM:當程式的狀態發生變化時,框架 (React.js / Vue.js) 會建立一個新的虛擬 DOM,這個樹狀包含最新的狀態資料
  2. 比較虛擬 DOM 和舊的虛擬 DOM:框架會將兩個虛擬 DOM 進行比對,找出彼此的差異
  3. 計算變化:框架會計算需要對實際 DOM 做的最小變化是什麼?例如更新、刪除 DOM 元素
  4. 更新真的 DOM:計算後,框架只會對需要變化的部分進行實際的 DOM 操作,而不是對整個頁面進行更新,如此可以大大降低效能處理。

而 Vue.js,就是我們上述提到的框架,他會先更新虛擬 DOM,再去比較新的虛擬 DOM 和舊的虛擬 DOM 之間的差異,最後只更新實際 DOM 中發生變化的部分。

強制重新渲染路由

我們在 <router-view /> 可以使用 :key 來觸發更新。當 :key 的值發生改變時,Vue 會認為這是一個新的路由,所以可以強制 Vue 重新渲染該路由及其子組件,達成我們想要的功能。

用 :key 重新渲染路由,他是更新整個頁面?還是有用到虛擬 DOM 的更新?

雖然我們是透過改變 :key 值來觸發更新,但實際運作仍然是基於比較虛擬 DOM 的差異來更新,而非整個頁面的更新,因此依然能透過最小化 DOM 的操作來提高效能。

▼ 新增 :key="globalStore.routeKey"

<template>
  <el-config-provider :locale="locale">
    <router-view :key="globalStore.routeKey" />
  </el-config-provider>
</template>

我希望不管在哪一頁,都能直接控制 routeKey++ ,觸發 App.vue 更新 <router-view />,因此我使用 pinia 全局狀態管理工具來達成

▼ 將 routeKey 放在 pinia 管理

import { defineStore } from 'pinia'

export type GlobalType = {
  routeKey: number
}

export const useGlobalStore = defineStore({
  id: 'global',
  state: (): GlobalType => ({
    routeKey: 0
  })
})

▼ 在每個檔案都能使用 globalStore.routeKey++ 重新渲染路由

<script>
import { useGlobalStore } from '@/stores'

const globalStore = useGlobalStore()

const onClick = () => {
  globalStore.routeKey++
}

</script>

總結

使用 :key 可以在不重新整理整個頁面的情況下,強制 Vue 重新渲染特定的路由及其內容。這是一種有效的技巧,特別是在需要手動控制路由切換時,或者在某些狀態發生變化時,需要強制重新渲染特定頁面的情況下。

有任何問題都歡迎留言告訴我唷,謝謝

歡迎給我點鼓勵,讓我知道你來過 :)

23
2
Subscribe
Notify of
guest

0 則留言
Inline Feedbacks
View all comments