記錄--極致舒適的Vue頁面保活方案

来源:https://www.cnblogs.com/smileZAZ/archive/2023/05/08/17382509.html
-Advertisement-
Play Games

這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 為了讓頁面保活更加穩定,你們是怎麼做的? 我用一行配置實現了 Vue頁面保活是指在用戶離開當前頁面後,可以在返回時恢覆上一次瀏覽頁面的狀態。這種技術可以讓用戶享受更加流暢自然的瀏覽體驗,而不會被繁瑣的操作打擾。 為什麼需要頁面保活? 頁面 ...


這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助

為了讓頁面保活更加穩定,你們是怎麼做的?

我用一行配置實現了

Vue頁面保活是指在用戶離開當前頁面後,可以在返回時恢覆上一次瀏覽頁面的狀態。這種技術可以讓用戶享受更加流暢自然的瀏覽體驗,而不會被繁瑣的操作打擾。

為什麼需要頁面保活?

頁面保活可以提高用戶的體驗感。例如,當用戶從一個帶有分頁的表格頁面(【頁面A】)跳轉到數據詳情頁面(【頁面B】),並查看了數據之後,當用戶從【頁面B】返回【頁面A】時,如果沒有頁面保活,【頁面A】會重新載入並跳轉到第一頁,這會讓用戶感到非常煩惱,因為他們需要重新選擇頁面和數據。因此,使用頁面保活技術,當用戶返回【頁面A】時,可以恢復之前選擇的頁碼和數據,讓用戶的體驗更加流暢。

如何實現頁面保活?

狀態存儲

這個方案最為直觀,原理就是在離開【頁面A】之前手動將需要保活的狀態存儲起來。可以將狀態存儲到LocalStoreSessionStoreIndexedDB。在【頁面A】組件的onMounted鉤子中,檢測是否存在此前的狀態,如果存在從外部存儲中將狀態恢復回來。

有什麼問題?

  • 浪費心智(麻煩/操心)。這個方案存在的問題就是,需要在編寫組件的時候就明確的知道跳轉到某些頁面時進行狀態存儲。
  • 無法解決子組件狀態。在頁面組件中還可以做到保存頁面組件的狀態,但是如何保存子組件呢。不可能所有的子組件狀態都在頁面組件中維護,因為這樣的結構並不是合理。

組件緩存

利用Vue的內置組件<KeepAlive/>緩存包裹在其中的動態切換組件(也就是<Component/>組件)。<KeepAlive/>包裹動態組件時,會緩存不活躍的組件,而不是銷毀它們。當一個組件在<KeepAlive/>中被切換時,activateddeactivated生命周期鉤子會替換mountedunmounted鉤子。最關鍵的是,<KeepAlive/>不僅適用於被包裹組件的根節點,也適用於其子孫節點。

<KeepAlive/>搭配vue-router即可實現頁面的保活,實現代碼如下:

<template>
  <RouterView v-slot="{ Component }">
    <KeepAlive>
      <component :is="Component"/>
    </KeepAlive>
  </RouterView>
</template>

有什麼問題?

  • 頁面保活不准確。上面的方式雖然實現了頁面保活,但是並不能滿足生產要求,例如:【頁面A】是應用首頁,【頁面B】是數據列表頁,【頁面C】是數據詳情頁。用戶查看數據詳情的動線是:【頁面A】->【頁面B】->【頁面C】,在這條動線中【頁面B】->【頁面C】的時候需要緩存【頁面B】,當從【頁面C】->【頁面B】的時候需要從換從中恢復【頁面B】。但是【頁面B】->【頁面A】的時候又不需要緩存【頁面B】,上面的這個方法並不能做到這樣的配置。

最佳實踐

最理想的保活方式是,不入侵組件代碼的情況下,通過簡單的配置實現按需的頁面保活。

【不入侵組件代碼】這條即可排除第一種方式的實現,第二種【組件緩存】的方式只是敗在了【按需的頁面保活】。那麼改造第二種方式,通過在router的路由配置上進行按需保活的配置,再提供一種讀取配置結合<KeepAlive/>include屬性即可。

路由配置

src/router/index.ts

import useRoutersStore from '@/store/routers';

const routes: RouteRecordRaw[] = [
  {
    path: '/',
    name: 'index',
    component: () => import('@/layout/index.vue'),
    children: [
      {
        path: '/app',
        name: 'App',
        component: () => import('@/views/app/index.vue'),
      },
      {
        path: '/data-list',
        name: 'DataList',
        component: () => import('@/views/data-list/index.vue'),
        meta: {
          // 離開【/data-list】前往【/data-detail】時緩存【/data-list】
          leaveCaches: ['/data-detail'],
        }
      },
      {
        path: '/data-detail',
        name: 'DataDetail',
        component: () => import('@/views/data-detail/index.vue'),
      }
    ]
  }
];

router.beforeEach((to: RouteLocationNormalized, from: RouteLocationNormalized, next: NavigationGuardNext) => {
  const { cacheRouter } = useRoutersStore();
  cacheRouter(from, to);
  next();
});

保活組件存儲

src/stroe/router.ts

import { RouteLocationNormalized } from 'vue-router';

const useRouterStore = defineStore('router', {
  state: () => ({
    cacheComps: new Set<string>(),
  }),
  actions: {
    cacheRouter(from: RouteLocationNormalized, to: RouteLocationNormalized) {
      if(
        Array.isArray(from.meta.leaveCaches) && 
        from.meta.leaveCaches.inclued(to.path) && 
        typeof from.name === 'string'
      ) {
        this.cacheComps.add(form.name);
      }
      if(
        Array.isArray(to.meta.leaveCaches) && 
        !to.meta.leaveCaches.inclued(from.path) && 
        typeof to.name === 'string'
      ) {
        this.cacheComps.delete(to.name);
      }
    },
  },
  getters: {
    keepAliveComps(state: State) {
      return [...state.cacheComps];
    },
  },
});

頁面緩存

src/layout/index.vue

<template>
  <RouterView v-slot="{ Component }">
    <KeepAlive :include="keepAliveComps">
      <component :is="Component"/>
    </KeepAlive>
  </RouterView>
</template>

<script lang='ts' setup>
import { storeToRefs } from 'pinia';
import useRouterStore from '@/store/router';

const { keepAliveComps } = storeToRefs(useRouterStore());
</script>

TypeScript提升配置體驗

import 'vue-router';

export type LeaveCaches = string[];

declare module 'vue-router' {
  interface RouteMeta {
    leaveCaches?: LeaveCaches;
  }
}

該方案的問題

  • 缺少通配符處理/*/**/index
  • 無法緩存/preview/:address這樣的動態路由。
  • 組件名和路由名稱必須保持一致。

總結

通過<RouterView v-slot="{ Component }">獲取到當前路由對應的組件,在將該組件通過<component :is="Component" />渲染,渲染之前利用<KeepAlive :include="keepAliveComps">來過濾當前組件是否需要保活。 基於上述機制,通過簡單的路由配置中的meta.leaveCaches = [...]來配置從當前路由出發到哪些路由時,需要緩存當前路由的內容。

本文轉載於:

https://juejin.cn/post/7216262593718173752

如果對您有所幫助,歡迎您點個關註,我會定時更新技術文檔,大家一起討論學習,一起進步。

 


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

-Advertisement-
Play Games
更多相關文章
  • 如果你在 Docker 環境中使用 WebSocket 並通過 Nginx 進行代理,可能需要進行一些額外的配置才能使 WebSocket 正常工作。 下麵是一些可能會導致 WebSocket 代理失敗的問題以及相應的解決方法: 檢查 Nginx 配置 在 Nginx 配置中,確保已經正確地設置了 ...
  • TTL是 Time To Live的縮寫,該欄位指定IP包被路由器丟棄之前允許通過的最大網段數量。TTL是IPv4報頭的一個8 bit欄位。 IPv4包頭中TTL是一個8 bit欄位,它位於IPv4包的第9個位元組。如下圖所示,每一行表示 32 bit(4位元組),位從0開始編號,即0~31。 TTL的 ...
  • (工作中,Oracle常用函數) 1、序言 Oracle提供了不少內置函數,熟練使用這些函數,可以大大提高我們工作效率。函數可以接受0個或多個入參,並返回一個輸出結果。 2、Oracle函數分類 Oracle函數分為單行函數和聚合函數 單行函數:對每一個函數應用在表的記錄中時,只能輸入一行結果,返回 ...
  • Hadoop官方網站 http://hadoop.apache.org/ Hadoop運行模式 本地模式:單機運行,只是用來演示一下官方案例。生產環境不用。 偽分散式模式:也是單機運行,但是具備Hadoop集群的所有功能,一臺伺服器模擬一個分散式的環境。個別缺錢的公司用來測試,生產環境不用。 完全分 ...
  • 主機名 ip ssh免密登陸 #修改主機名 hostnamectl set-hostname node1 #修改ip地址 vim /etc/sysconfig/network-scripts/ifcfg-ens33 #node1 IPADDR="192.168.88.101" NETMASK="22 ...
  • (Oracle常用SQL) 工作中我們基本上每天都要與資料庫打交道,資料庫的知識點呢也特別多,全部記住呢也是不可能的,也沒必要把所有的記住(有些語句命令可能我們一輩子都用不到)。 所以呢在工作之餘,把工作中經常用到的一些語句整理出來,忘記的時候可以當做字典來查。 個人在工作中用Oracle資料庫比較 ...
  • 京東小程式近年來支持了越來越多的業務和應用,做好小程式的摺疊屏的適配也是符合未來的發展趨勢,能為用戶和業務方提供更好的體驗和價值。 ...
  • > 近日來對Kotlin的使用頻率越來越高, 也對自己近年來寫過的Kotlin代碼嘗試進行一個簡單的整理. 翻到了自己五年前第一次使用Kotlin來完成的一個項目([貝塞爾曲線](https://juejin.cn/post/6844903556173004807)), 一時興起, 又用發展到現在的 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...