页面缓存根据需求分为以下3类
- 类小程序:根据用户的跳转方法来决定如何操作页面缓存堆栈
- 历史记录:根据用户访问的历史记录缓存一定数量的页面,超过限定数量时采用新进先出
- 面包屑:根据面包屑结构,缓存当前页面的祖先页面
类小程序
- 需要解决的问题
- 实现以下常用跳转方法
- navigateTo 保留当前页面,跳转到应用内的某个页面
- redirectTo 关闭当前页面,跳转到应用内的某个页面
- reLaunch 关闭所有页面,打开到应用内的某个页面
- navigateBack 关闭当前页面,返回上一页面或多级页面
- 以上跳转方式如何在 router-link 中实现
- 需要拦截 history、router 下对应的方法
- 需要拦截浏览器返回按钮
- 实现以下常用跳转方法
历史记录
- 略
面包屑
- 以下例子实现了对 HomeView 这个父页面的组件的缓存
- keep-alive 和 router-view 配合使用实现父级页面缓存
<template>
<div>
<nav>
<router-link to="/">Home</router-link> |
<router-link to="/about">About</router-link> |
<router-link to="/about2">About2</router-link>
</nav>
<keep-alive :include="keepAliveInclude">
<!-- keep-alive 以第一个 slot 的 key 为钥匙寻找对应的组件实例的,:key="$route.fullPath"用以缓存不同路由的同一组件 -->
<router-view name="default" :key="$route.fullPath" />
</keep-alive>
</div>
</template>
<script lang="ts">
import { keepAliveInclude } from "@/utils/pageKeepAliveInclude";
import { defineComponent } from "vue";
export default defineComponent({
setup() {
return {
// 需要缓存的组件名称,包含父页面路由信息中 component 或 components 中所有组件的名称
keepAliveInclude,
};
},
});
</script>
- 路由
import Vue from "vue";
import VueRouter, { RouteConfig } from "vue-router";
import HomeView from "../views/HomeView.vue";
import { setKeepAliveInclude } from "@/utils/pageKeepAliveInclude";
import HeadAndSideVue from "@/components/HeadAndSide.vue";
Vue.use(VueRouter);
const routes: Array<RouteConfig> = [
{
path: "/",
component: HeadAndSideVue,
meta: {
// 这个组件不需要缓存,不会被包含到 keepAliveInclude 中
noKeepAlive: true,
},
children: [
{
path: "",
name: "home",
component: HomeView,
},
{
path: "about",
name: "about",
component: () =>
import(/* webpackChunkName: "about" */ "../views/AboutView.vue"),
meta: {
// 当前页面的父级页面的 name
fatherPageName: "home",
},
},
{
path: "about2",
name: "about2",
component: () =>
import(/* webpackChunkName: "about" */ "../views/AboutView.vue"),
meta: {
fatherPageName: "home",
},
},
],
},
];
const router = new VueRouter({
mode: "history",
base: process.env.BASE_URL,
routes,
});
// 在路由拦截器中设置 keep-alive 的 include 绑定值
router.afterEach(setKeepAliveInclude);
export default router;
- setKeepAliveInclude 和 keepAliveInclude
import router from "@/router";
import { Component, Ref, nextTick, ref } from "vue";
import { Route } from "vue-router";
export const keepAliveInclude: Ref<string[]> = ref([]);
function arrAdd<T>(arr: T[], item: T) {
if (!arr.includes(item)) arr.push(item);
}
function _setKeepAliveInclude(route: Route) {
if (!route.matched.length) return;
route.matched.forEach((matched) => {
if (matched.meta?.noKeepAlive) return;
Object.values(matched.components).forEach((component) => {
const name = (component as Component).name;
if (name) {
arrAdd(keepAliveInclude.value, name);
} else {
console.error(component);
throw new Error(
"路由中需要缓存(未配置meta.noKeepAlive)的组件,其组件名是必须的。以上组件缺少组件名:"
);
}
});
});
if (route.meta?.fatherPageName) {
const { route: fatherRoute } = router.resolve({
name: route.meta.fatherPageName,
});
_setKeepAliveInclude(fatherRoute);
}
}
export function setKeepAliveInclude(to: Route) {
// 从子页面跳转到父页面时,等待 keepAlive 根据 include 包含的父组件名称获取缓存的实例
// 然后重新生成 include,才把父页面的组件名称从 include 中删除,从而清除父页面的缓存
nextTick(() => {
keepAliveInclude.value.length = 0;
// 根据面包屑层级,递归把父页面使用到的组件添加到include中
if (to.meta?.fatherPageName) {
const { route: fatherRoute } = router.resolve({
name: to.meta.fatherPageName,
});
_setKeepAliveInclude(fatherRoute);
}
});
}
标签:缓存,name,meta,router,import,页面
From: https://www.cnblogs.com/qq3279338858/p/17914516.html