Vue3中KeepAlive的使用

来源:https://www.cnblogs.com/evenshry/archive/2023/03/23/17246574.html
-Advertisement-
Play Games

備忘錄模式(Memento Pattern):是一種行為型設計模式,在不破壞封裝性的前提下,捕獲一個對象的內部狀態,併在該對象之外保存這個狀態。在JavaScript中,可以使用閉包來實現備忘錄模式。 備忘錄模式通常用於處理用戶界面的狀態。當用戶與應用程式交互時,應用程式會根據用戶的輸入更改其狀態。 ...


  我們在開發一個功能是,經常會遇到從一個列表頁面,點擊列表項跳轉到詳情頁面的需求,理想的情況下,從詳情頁面返回到列表頁,應該回到跳轉前的狀態,可以繼續瀏覽其他內容;但是在沒做任何處理的情況下,返回列表頁後,列表頁會被刷新,回到初始的狀態,這就與我們的預設不符;為了實現這樣的需求,我們需要使用keep-alive組件來緩存列表頁面的狀態,讓其不被刷新,這樣就可以愉快的繼續瀏覽啦。

  下麵就是我們使用keep-alive組件的一些步驟:(ps:項目使用vue3、vue-router、pinia、typescript)

1、聲明路由的Meta擴展數據類型,用來在路由中配置哪些頁面需要被緩存

router.d.ts

import "vue-router";

declare module "vue-router" {

  interface RouteMeta extends MyRoute.RouteMeta {
    title: string;
    keepAlive?: boolean; // 該路由頁面是否需要緩存
    keepAlivePages?: Array<string>;  // 配置需要緩存的跳回來源(從某頁面回到該頁面,該頁面緩存,其他頁面回到該頁面,該頁面不緩存)
    canBack?: boolean; // 是否可以返回
  }

}

 

2、配置路由信息,以文章列表和詳情頁面為例

分模塊配置路由文件library.ts

import { RouteComponent, RouteRecordRaw } from "vue-router";

const routes: Array<RouteRecordRaw> = [
 {
    path: "library/list",
    name: "libraryList",
    meta: { title: "文章列表", keepAlive: true, keepAlivePages: ["libraryDetail"] },
    component: (): RouteComponent => {
      return import(/* webpackChunkName: "pages_knowledge_library" */ "@/views/pages/knowledge/library/index.vue");
    }
  },
  {
    path: "library/detail",
    name: "libraryDetail",
    meta: { title: "文章詳情", canBack: true },
    component: (): RouteComponent => {
      return import(/* webpackChunkName: "pages_knowledge_library_detail" */ "@/views/pages/knowledge/library/detail.vue");
    }
  }
];

export default routes;

 

3、聲明頁面組件的名稱,與配置的名稱一致:keep-alive 組件會根據組件的 name 選項進行匹配,所以組件如果想要條件性地被 keep-alive 緩存,就必須顯式聲明一個 name 選項。

在 3.2.34 或以上的版本中,使用 <script setup> 的單文件組件會自動根據文件名生成對應的 name 選項,即使是在配合 <KeepAlive> 使用時也無需再手動聲明。

但在項目中我們是分模版開發,業務組件文件重名的幾率還是挺大的,所以我們還是需要顯式聲明組件的name屬性。

library/index.vue

<template>
<!-- 頁面模版 -->
</template>

<script lang="ts">
import { defineComponent } from "vue";
export default defineComponent({ name: "libraryList" });
</script>

<script lang="ts" setup>
// 頁面綁定數據
<script>

library/detail.vue

<template>
<!-- 頁面模版 -->
</template>

<script lang="ts">
import { defineComponent } from "vue";
export default defineComponent({ name: "libraryDetail" });
</script>

<script lang="ts" setup>
// 頁面綁定數據
<script>

 

3、定義一個Store用來緩存需要被緩存的頁面集合

keepAliveStore.ts

import { defineStore } from "pinia";

export interface KeepAliveState {
  keepAliveComponents: Array<any>;
}

export const keepAliveStore = defineStore("keepAlive", {
    
  state: (): KeepAliveState => {
    return {
      keepAliveComponents: []
    };
  },

  getters: {
    getKeepAliveComponents(state) {
      return state.keepAliveComponents;
    }
  },

  actions: {
      
    // 加入到緩存隊列
    setKeepAlive(component: any) {
      if (!this.keepAliveComponents.includes(component)) {
        this.keepAliveComponents.push(component);
      }
    },

    // 從緩存隊列移除
    removeKeepAlive(component: any) {
      const index = this.keepAliveComponents.indexOf(component);
      if (index !== -1) {
        this.keepAliveComponents.splice(index, 1);
      }
    }

  }
});

4、路由守衛處理:在路由進入之前讀取Meta擴展數據,如果配置了緩存,就加入到緩存隊列中;在路由離開之前判斷目標路由的Meta擴展數據,如果該頁面與配置的來源頁面不匹配,則將目標路由從緩存隊列中移除

router/index.ts

const router = createRouter({
  history: createWebHashHistory(import.meta.env.BASE_URL),
  routes
});

// --- beforeRouter --- //
router.beforeEach((to, _from, next) => {

  const { KeepAliveStore } = usePiniaStore();
  const meta = to.meta || {};

  // 加入緩存隊列
  if (meta.keepAlive) {
    KeepAliveStore.setKeepAlive(to.name);
  }  

  // 做一些其他的事情
});

// ---afterRouter --- //
router.afterEach((to, from) => {

  const { KeepAliveStore } = usePiniaStore();

  // 如果配置了目標緩存,即:目標頁面不在目標緩存中,移除當前頁面緩存
  if (from.meta.keepAlivePages) {
    if (from.meta.keepAlivePages.indexOf(to.name as string) == -1) {
      KeepAliveStore.removeKeepAlive(from.name);
    }
  }

  // 做一些其他的事情
});

 

5、keep-alive組件的使用:取出緩存隊列中的集合,配置給include屬性,keep-alive組件便能把配置的路由頁面給緩存起來了;同時也可以設置max最大緩存數,避免緩存太多導致性能下降

RouterView.vue

<template>
  <router-view v-slot="{ Component }">
    <transition name="fade" mode="out-in" appear>
      <keep-alive :include="keepAliveComponents" :max="10">
        <component :is="Component" />
      </keep-alive>
    </transition>
  </router-view>
</template>

<script lang="ts" setup>
import { usePiniaStore } from "@/store";
    
const { KeepAliveStore } = usePiniaStore();
const keepAliveComponents = KeepAliveStore.getKeepAliveComponents;
</script>

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • pdf文件能夠比較好的保留源格式,傳輸也比較方便,現PC端瀏覽器基本都可直接查看pdf文件,只是界面風格不怎麼統一,但是手機端查看pdf文件就不能很好的只“預覽”,往往都是自動下載到本地再查看,今天分享pdf.js,主要用於線上pdf預覽,平時我使用比較多的場景就是培訓手冊。 我用的是1.1.159 ...
  • ?問題 :如何添加token,解決鑒權問題 方案:通過登錄頁面,發送請求,獲取到token值,並把token值存儲(localStorage、sessionStorage、cookieStore),示例如下: <template> <el-form label-width="80px"> <el-f ...
  • 使用 glup 打包組件庫並實現按需載入 當我們使用 Vite 庫模式打包的時候,vite 會將樣式文件全部打包到同一個文件中,這樣的話我們每次都要全量引入所有樣式文件做不到按需引入的效果。所以打包的時候我們可以不讓 vite 打包樣式文件,樣式文件將使用 gulp 進行打包。那麼本篇文章將介紹如何 ...
  • 在使用阿裡雲伺服器部署完flask項目後,實際訪問網站發現網站載入速度慢 問題分析: 打開開發者工具-網路,發現echarts文件及其3D庫載入時間過長,頁面空白時間長,用戶等待時間長,如下圖 解決辦法: 1、利用CDN內容分髮網絡使用戶根據自己網路的特點更快、更穩定地訪問到節點伺服器中的資源,從而 ...
  • CSS 為實現重疊效果,將 margin-top 設為負值時,div 背景被 img 圖片遮擋 一、未實現重疊效果 <body> <img src="https://cdn.uviewui.com/uview/swiper/swiper2.png" style="width: 375px;" alt ...
  • <template> <el-button style="float: right; margin: 10px" type="primary" @click="export2">導出</el-button> <!-- 導出表格 start--> <el-table class="tableExpor ...
  • const: 這個最簡單,只需記住是聲明的常量,定義的時候必須聲明const的具體值,且之後不允許改變const的值 var和let區別 1、由於js引擎存在預解析,會把var變數名進行提升 對於var來說是這樣執行的 var m; console.log(m); m=10; let不存在變數提升, ...
  • ### canvas特性 標簽中的文本只有在瀏覽器下支持canvas標簽時才顯示 行內塊元素 高度設置在標簽屬性上 ### 填充色設置 ctx.fillStyle="#ff0000" ### 線條顏色設置 ctx.strokeStyle="ff0000" ### 線條粗細 ctx.lineWidth ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...