首頁 > web前端 > Vue.js > 主體

分享一個極致舒適的Vue頁面保活方案

藏色散人
發布: 2023-04-10 16:29:03
轉載
1390 人瀏覽過

這篇文章為大家帶來了關於Vue的相關知識,其中主要跟大家分享一個極致舒適的Vue頁面保活方案,有代碼示例,有興趣的朋友下面一起來看一下吧,希望對大家有幫助。

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

我用一行設定實作了

分享一個極致舒適的Vue頁面保活方案

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

為什麼需要頁面保活?

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

如何實現頁面保活?

狀態儲存

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

有什麼問題?

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

元件快取

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

<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 &#39;@/store/routers&#39;;

const routes: RouteRecordRaw[] = [
  {
    path: &#39;/&#39;,
    name: &#39;index&#39;,
    component: () => import(&#39;@/layout/index.vue&#39;),
    children: [
      {
        path: &#39;/app&#39;,
        name: &#39;App&#39;,
        component: () => import(&#39;@/views/app/index.vue&#39;),
      },
      {
        path: &#39;/data-list&#39;,
        name: &#39;DataList&#39;,
        component: () => import(&#39;@/views/data-list/index.vue&#39;),
        meta: {
          // 离开【/data-list】前往【/data-detail】时缓存【/data-list】
          leaveCaches: [&#39;/data-detail&#39;],
        }
      },
      {
        path: &#39;/data-detail&#39;,
        name: &#39;DataDetail&#39;,
        component: () => import(&#39;@/views/data-detail/index.vue&#39;),
      }
    ]
  }
];

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

保活元件儲存

src/stroe /router.ts

import { RouteLocationNormalized } from &#39;vue-router&#39;;

const useRouterStore = defineStore(&#39;router&#39;, {
  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 === &#39;string&#39;
      ) {
        this.cacheComps.add(form.name);
      }
      if(
        Array.isArray(to.meta.leaveCaches) && 
        !to.meta.leaveCaches.inclued(from.path) && 
        typeof to.name === &#39;string&#39;
      ) {
        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 setup>
import { storeToRefs } from &#39;pinia&#39;;
import useRouterStore from &#39;@/store/router&#39;;

const { keepAliveComps } = storeToRefs(useRouterStore());
</script>
登入後複製

TypeScript提升配置体验

import &#39;vue-router&#39;;

export type LeaveCaches = string[];

declare module &#39;vue-router&#39; {
  interface RouteMeta {
    leaveCaches?: LeaveCaches;
  }
}
登入後複製

该方案的问题

  • 缺少通配符处理/*/**/index
  • 无法缓存/preview/:address这样的动态路由。
  • 组件名和路由名称必须保持一致。

总结

通过<routerview v-slot="{ Component }"></routerview>获取到当前路由对应的组件,在将该组件通过<component :is="Component"></component>渲染,渲染之前利用<keepalive :include="keepAliveComps"></keepalive>来过滤当前组件是否需要保活。 基于上述机制,通过简单的路由配置中的meta.leaveCaches = [...]来配置从当前路由出发到哪些路由时,需要缓存当前路由的内容。【推荐学习:《vue.js视频教程》】

如果大家有其他保活方案,欢迎留言交流哦!

以上是分享一個極致舒適的Vue頁面保活方案的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:juejin.im
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
最新問題
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!