首页 > 其他分享 >记录--极致舒适的Vue页面保活方案

记录--极致舒适的Vue页面保活方案

时间:2023-05-08 18:01:39浏览次数:36  
标签:Vue -- 保活 缓存 import 组件 router 页面

这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助

为了让页面保活更加稳定,你们是怎么做的?

我用一行配置实现了

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

如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。

 

标签:Vue,--,保活,缓存,import,组件,router,页面
From: https://www.cnblogs.com/smileZAZ/p/17382509.html

相关文章

  • 新增节代码
    #include"stdafx.h"#include<stdio.h>#include<windows.h>#include<malloc.h>#defineShellCodeIen0x12#defineMessageBoxAdder0x77D507EABYTEShellCode[]={ 0x6A,00,0x6A,00,0x6A,00,0x6A,00, 0xE8,00,00,00,00, 0xE9,00,00......
  • PKUSC 2023
    不保证Subtask完全准确。题面与\(100\%\)数据范围大致准确。D1T1给定两个长度相同的字符串\(S[1\cdotsn],T[1\cdotsn]\),你需要对每个\(1\lei\len\)输出:如果将\(S_i\)替换为\(T_i\),得到的新字符串的border长度是多少。一个字符串\(S\)的border长度定义为......
  • 未提供与“Course.Course(string, int, int)”的所需参数“Name”对应的参数
    当传给类中的参数不确定有无时,则要给父类加个无参构造方法 ......
  • python 打包
    1,单文件打包pyinstaller-F-wfile.py-F:-w::启动exe文件,不显示控制台2,多文件打包 文件结构:testmain.pyset.py如果使用:pyinstaller-F-wmain.py发生问题:相互依赖的文件,打包后无法引用,导致报错可以使用:pyinstaller-Dmain.py-pset.py假......
  • 数据库简介
    一数据库管理软件的由来基于我们之前所学,数据要想永久保存,都是保存于文件中,毫无疑问,一个文件仅仅只能存在于某一台机器上。如果我们暂且忽略直接基于文件来存取数据的效率问题,并且假设程序所有的组件都运行在一台机器上,那么用文件存取数据,并没有问题。很不幸,这些假设都是你自......
  • ChatGLM-6B本地化部署
    一、硬件要求量化等级最低GPU显存(推理)最低GPU显存(高效参数微调)FP16(无量化)13GB14GBINT88GB9GBINT46GB7GB二、环境要求需先安装git、python三、下载源码1mkdir/gpt2cdgpt3gitclonehttps://github.com/THUDM/ChatGLM-6B.git ......
  • 1113. 红与黑
    题目描述地砖有红和黑两种颜色,站在给定的某个黑色地砖上,问有多少块黑色地砖可达?f1dfs计算连通性基本分析dfs返回什么?从当前节点出发可达的黑色地砖个数dfs怎么实现?初始化cnt;修改vis状态;枚举可选的4相邻地砖(越界跳过,访问过跳过,红色跳过,累加下一步可达的个数)返回cnt......
  • uniapp读取本地通讯录
    官方文档:https://uniapp.dcloud.net.cn/api/system/contact.html#addphonecontactcreated(){//#ifdefAPP-PLUSthis.getLocalContact()//#endif},methods:{getLocalContact(){lettype=plus.contacts.ADDRESSBOOK_PHONEplu......
  • 搭建 Kubernetes 集群
    简介Kubernetes是一个开源系统,用于容器化应用的自动部署、扩缩和管理。它将构成应用的容器按逻辑单位进行分组以便于管理和发现。搭建环境:CentOSv7.6.1810docker-ce-versionv23.0.5kubernetes-versionv1.23.6本次使用2台服务器进行搭建,运行下面命令写入/etc/hosts文件(......
  • jQuery
    jQueryjQuery介绍jQuery是一个轻量级的、兼容多浏览器的JavaScript库。jQuery使用户能够更方便地处理HTMLDocument、Events、实现动画效果、方便地进行Ajax交互,能够极大地简化JavaScript编程。它的宗旨就是:“Writeless,domore.“jQuery的优势一款轻量级的JS框架。jQue......