最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

基于Vue3+Pinia的移動端頁面緩存策略的解決方案

 更新時間:2025年10月31日 08:31:12   作者:橙某人  
最近小編在開發(fā)移動端 Web 應(yīng)用時,遇到了一個問題:頁面緩存,經(jīng)過一番折騰和還有AI的加持,小編也順利解決了,今天就來和大家分享這個基于導(dǎo)航棧的智能緩存策略,需要的朋友可以參考下

第1步:緩存策略的目的與意義

在移動端Web應(yīng)用中,咱們經(jīng)常遇到這樣的用戶場景:

  • 商品列表 → 商品詳情 → 返回列表:用戶希望回到之前瀏覽的位置。
  • 菜單 → 商品列表:用戶希望看到最新的商品信息。
  • 表單填寫過程:用戶在多個步驟(子頁面)間切換時保持已填寫的數(shù)據(jù)。

傳統(tǒng)方案的痛點:

// 傳統(tǒng)keep-alive方案的問題
<keep-alive :include="['ProductList', 'UserProfile']">
  <router-view />
</keep-alive>
  • 問題1:無法區(qū)分進(jìn)入方式(從菜單進(jìn)入 vs 從其他頁面返回)。
  • 問題2:緩存策略過于粗暴,要么全緩存要么不緩存。
  • 問題3:無法根據(jù)業(yè)務(wù)邏輯動態(tài)控制緩存行為。

第2步:實現(xiàn)原理與核心設(shè)計思想

核心設(shè)計理念

咱們的方案基于一個簡單的思想:模擬整個應(yīng)用的"導(dǎo)航棧"行為。

用戶操作流程:菜單頁 → 頁面A → 頁面B → 返回A → 返回菜單頁 → 重新進(jìn)入A
期望行為:  清空 → 新建A → 緩存A → 恢復(fù)A → 清空 → 新建A

菜單頁概念說明

在開始介紹下面內(nèi)容之前,咱們先明確一個重要概念:菜單頁。

什么是菜單頁?

答:它類似于App的首頁或主導(dǎo)航頁面。

為什么需要菜單頁?

答:定期清理緩存,避免內(nèi)存泄漏,確保用戶每次從主入口開始都是干凈的狀態(tài)。

原理流程圖

一圖勝千言,瞧瞧:

關(guān)鍵技術(shù)點

實時導(dǎo)航棧管理

// 檢查是否為返回到已存在的路由
const isBackToExistingRoute = (targetFullPath) => {
  return state.navigationStack.some(route => route.fullPath === targetFullPath);
};

// 通過檢查導(dǎo)航棧判斷是前進(jìn)還是返回
const isBackNavigation = isBackToExistingRoute(to.fullPath);

if (isBackNavigation) {
  // 返回操作:移除目標(biāo)路由之后的所有路由
  backToRoute(to.fullPath);
} else {
  // 前進(jìn)操作:添加新路由到棧中,緩存離開的頁面
  pushRoute(to.fullPath, to.name);
  if (from.meta?.keepAlive && from.name) {
    state.cachedComponents.add(from.name);
  }
}

緩存時機(jī)

  • 前進(jìn)導(dǎo)航:緩存離開的頁面(如果配置了keepAlive)
  • 返回導(dǎo)航:清理目標(biāo)頁面之后的所有緩存
  • 菜單重置:清空所有緩存,確保新鮮狀態(tài)

第3步:核心代碼實現(xiàn)

在實際項目中,小編是使用 Pinia 來完成這塊緩存功能的開發(fā),具體如下:

import { reactive, toRefs, computed } from "vue";
import { defineStore } from "pinia";

export const useRouteCacheStore = defineStore("routeCache", () => {
  const state = reactive({
    navigationStack: [],           // 導(dǎo)航歷史棧 [{fullPath, name}]
    cachedComponents: new Set(),   // 緩存的組件名稱列表
    menuPath: '/menu'             // 菜單頁面路徑
  });

  /**
   * 計算屬性:緩存組件列表
   * @description 將 Set 類型的緩存組件轉(zhuǎn)換為數(shù)組格式
   * @returns {string[]} 緩存的組件名稱數(shù)組
   */
  const cacheIncludeList = computed(() => {
    return Array.from(state.cachedComponents);
  });

  /**
   * 檢查是否為返回到已存在的路由
   * @description 通過檢查導(dǎo)航棧中是否存在目標(biāo)路徑來判斷是否為返回操作
   * @param {string} targetFullPath - 目標(biāo)路由的完整路徑
   * @returns {boolean} 如果路由已存在于導(dǎo)航棧中返回 true,否則返回 false
   */
  const isBackToExistingRoute = (targetFullPath) => {
    return state.navigationStack.some(route => route.fullPath === targetFullPath);
  };

  /**
   * 添加路由到棧中
   * @description 如果路由不存在于導(dǎo)航棧中,則將其添加到棧頂
   * @param {string} fullPath - 路由的完整路徑
   * @param {string} name - 路由的名稱
   * @returns {void}
   */
  const pushRoute = (fullPath, name) => {
    if (!isBackToExistingRoute(fullPath)) {
      state.navigationStack.push({ fullPath, name });
    }
  };

  /**
   * 返回到指定路由,移除后續(xù)路由
   * @description 找到目標(biāo)路由在棧中的位置,移除其后的所有路由及其緩存,然后截斷導(dǎo)航棧
   * @param {string} targetFullPath - 目標(biāo)路由的完整路徑
   * @returns {void}
   */
  const backToRoute = (targetFullPath) => {
    const targetIndex = state.navigationStack.findIndex(route => route.fullPath === targetFullPath);
    if (targetIndex !== -1) {
      // 移除目標(biāo)路由之后的所有路由的緩存
      const removedRoutes = state.navigationStack.slice(targetIndex + 1);
      removedRoutes.forEach(route => {
        if (route.name) {
          state.cachedComponents.delete(route.name);
        }
      });
      // 截斷導(dǎo)航棧
      state.navigationStack = state.navigationStack.slice(0, targetIndex + 1);
    }
  };

  /**
   * 處理路由導(dǎo)航
   * @description 根據(jù)導(dǎo)航類型(前進(jìn)/返回)處理路由棧和組件緩存,進(jìn)入菜單頁時清空所有緩存
   * @param {Object} to - 目標(biāo)路由對象
   * @param {string} to.fullPath - 目標(biāo)路由的完整路徑
   * @param {string} to.name - 目標(biāo)路由的名稱
   * @param {Object} to.meta - 目標(biāo)路由的元信息
   * @param {Object} from - 來源路由對象
   * @param {string} from.fullPath - 來源路由的完整路徑
   * @param {string} from.name - 來源路由的名稱
   * @param {Object} from.meta - 來源路由的元信息
   * @param {boolean} from.meta.keepAlive - 是否需要緩存該組件
   * @returns {void}
   */
  const handleNavigation = (to, from) => {
    const isBackNavigation = isBackToExistingRoute(to.fullPath);
    
    if (isBackNavigation) {
      // 返回操作:移除目標(biāo)路由之后的所有路由
      backToRoute(to.fullPath);
    } else {
      // 前進(jìn)操作:添加新路由到棧中
      pushRoute(to.fullPath, to.name);
      if (from.meta?.keepAlive && from.name) {
        state.cachedComponents.add(from.name);
      }
    }

    // 進(jìn)入菜單頁時,清空所有緩存
    if (to.fullPath === state.menuPath) {
      state.cachedComponents.clear();
    }
  };

  return {
    ...toRefs(state),
    cacheIncludeList,
    handleNavigation,
  };
});

沒多少代碼哈,小編也都貼心寫明了詳細(xì)注釋,應(yīng)該都能讀懂哈。

然后,就是在路由守衛(wèi)這里統(tǒng)一攔截所有的路由進(jìn)行處理:

import router from "@/router";
import { useRouteCacheStore } from '@/stores/modules/routeCache'

router.beforeEach((to, from, next) => {
  const routeCacheStore = useRouteCacheStore()
  
  // 處理路由緩存邏輯
  routeCacheStore.handleNavigation(to, from)
  
  next()
})

最后,在組件視圖這塊應(yīng)用動態(tài)緩存數(shù)據(jù):

<!-- src/layouts/BasicLayout.vue -->
<template>
  <div class="basic-layout">
    <keep-alive :include="cacheIncludeList">
      <router-view />
    </keep-alive>
  </div>
</template>

<script setup>
import { computed } from 'vue'
import { useRouteCacheStore } from '@/stores/modules/routeCache'

const routeCacheStore = useRouteCacheStore()

/** @description 獲取需要緩存的組件列表 */
const cacheIncludeList = computed(() => routeCacheStore.cacheIncludeList)
</script>

在路由配置中,記得標(biāo)明哪些路由是需要緩存的即可,示例:

// src/router/index.js
const routes = [
  {
    path: '/menu',
    name: 'Menu',
    component: () => import('@/views/menu/index.vue')
  },
  {
    path: '/product-list',
    name: 'ProductList',
    component: () => import('@/views/product/list.vue'),
    meta: {
      keepAlive: true // 標(biāo)記需要緩存
    }
  },
  {
    path: '/product-detail/:id',
    name: 'ProductDetail',
    component: () => import('@/views/product/detail.vue')
    // 詳情頁不需要緩存
  }
]

第4步:技術(shù)細(xì)節(jié)解析

fullPath的重要性

在移動端應(yīng)用中,同一個頁面可能因為不同的查詢參數(shù)而展示不同的內(nèi)容:

// 場景1:不同分類的商品列表
/product-list?category=phone&sort=price
/product-list?category=laptop&sort=sales

// 場景2:不同頁碼的列表
/product-list?page=1
/product-list?page=3

使用fullPath可以正確區(qū)分這些頁面,避免緩存混亂。

實時棧管理的優(yōu)勢

傳統(tǒng)方案:棧不實時更新,容易出現(xiàn)判斷錯誤。如:

菜單 → A → 菜單 → A (第二次進(jìn)入A時,棧中還有A,誤判為返回操作)

咱們的方案:實時移除離開的頁面。如:

菜單 → A(棧:[A]) → 菜單(棧:[],A被移除) → A(棧:[A],正確判斷為新進(jìn)入)

總結(jié)

這套基于導(dǎo)航棧的智能緩存策略完美解決了移動端頁面緩存難題!核心優(yōu)勢包括精準(zhǔn)控制緩存時機(jī)、保持頁面狀態(tài)同時確保數(shù)據(jù)新鮮度,應(yīng)該比較適合那些移動端Web應(yīng)用。

以上就是基于Vue3+Pinia的移動端頁面緩存策略的解決方案的詳細(xì)內(nèi)容,更多關(guān)于Vue3 Pinia移動端頁面緩存策略的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Vue項目配置跨域訪問和代理proxy設(shè)置方式

    Vue項目配置跨域訪問和代理proxy設(shè)置方式

    這篇文章主要介紹了Vue項目配置跨域訪問和代理proxy設(shè)置方式,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-09-09
  • Vue?elementUI實現(xiàn)樹形結(jié)構(gòu)表格與懶加載

    Vue?elementUI實現(xiàn)樹形結(jié)構(gòu)表格與懶加載

    這篇文章主要介紹了通過Vue和elementUI實現(xiàn)樹形結(jié)構(gòu)表格與懶加載,文中的示例代碼講解詳細(xì),感興趣的小伙伴快來跟隨小編一起學(xué)習(xí)一下吧
    2022-01-01
  • vue 解決異步數(shù)據(jù)更新問題

    vue 解決異步數(shù)據(jù)更新問題

    今天小編就為大家分享一篇vue 解決異步數(shù)據(jù)更新問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-10-10
  • 使用Vue簡單實現(xiàn)一個上拉加載更多分頁組件

    使用Vue簡單實現(xiàn)一個上拉加載更多分頁組件

    上拉加載更多的分頁功能大家應(yīng)該都見過或者使用過了吧,那么有多少同學(xué)自己實現(xiàn)過嗎,本文我們來簡單實現(xiàn)一個上拉加載更多分頁組件吧
    2024-11-11
  • Vue實現(xiàn)將頁面區(qū)域?qū)С鰹閜df

    Vue實現(xiàn)將頁面區(qū)域?qū)С鰹閜df

    文章介紹了兩種將前端頁面指定區(qū)域?qū)С鰹镻DF的純前端實現(xiàn)方法,方式一使用jsPDF和html2canvas將特定區(qū)域轉(zhuǎn)化為圖片,再將圖片轉(zhuǎn)化為PDF,適用于小區(qū)域轉(zhuǎn)換,但存在翻頁時內(nèi)容拆分的問題,方式二使用html2pdf.js,支持自動分頁,適用于較大區(qū)域的轉(zhuǎn)換
    2025-10-10
  • Vue.js使用Vapor Mode的方法小結(jié)

    Vue.js使用Vapor Mode的方法小結(jié)

    Vapor Mode是Vue 3.6推出的一個新的高效渲染模式,它實現(xiàn)了無虛擬DOM并大幅度提升性能, 下面就來詳細(xì)的介紹一下使用Vapor Mode的方法小結(jié),感興趣的可以了解一下
    2026-05-05
  • vue-element-admin開發(fā)教程(v4.0.0之后)

    vue-element-admin開發(fā)教程(v4.0.0之后)

    由于vue-element-admin的架構(gòu)再4.0.0版本后做了重構(gòu),整體結(jié)構(gòu)上和之前的還是很相似的,但是也有些變化,本文就介紹vue-element-admin開發(fā)教程(v4.0.0之后),感興趣的可以了解一下
    2022-04-04
  • vue3+ts使用bus事件總線的示例代碼

    vue3+ts使用bus事件總線的示例代碼

    這篇文章主要介紹了vue3+ts使用bus事件總線,文中給大家提到了vue總線機(jī)制(bus)的相關(guān)知識,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-08-08
  • VUE中filters過濾器的兩種用法實例

    VUE中filters過濾器的兩種用法實例

    vue中過濾器的作用可被用于一些常見的文本格式化,也就是修飾文本,但是文本內(nèi)容不會改變,下面這篇文章主要給大家介紹了關(guān)于VUE中filters過濾器的兩種用法,需要的朋友可以參考下
    2022-04-04
  • 詳解vue組件開發(fā)腳手架

    詳解vue組件開發(fā)腳手架

    本篇文章給大家詳細(xì)分析了vue組件開發(fā)腳手架的相關(guān)內(nèi)容以及知識點,對此有興趣的朋友可以學(xué)習(xí)參考下。
    2018-06-06

最新評論

东辽县| 塘沽区| 杭锦旗| 集安市| 仁布县| 蛟河市| 措美县| 大埔区| 芮城县| 昂仁县| 长武县| 时尚| 桐乡市| 唐山市| 新巴尔虎右旗| 贞丰县| 阜康市| 哈尔滨市| 景谷| 肥城市| 福贡县| 邯郸市| 浦江县| 巫溪县| 湘潭县| 贡山| 辽阳市| 平湖市| 永仁县| 烟台市| 班戈县| 建阳市| 锦屏县| 婺源县| 库伦旗| 宜州市| 玛曲县| 论坛| 屏边| 衡阳市| 延吉市|