Vue3 中 keepAlive 如何搭配 VueRouter 来更自由的控制页面的状态缓存?

这篇具有很好参考价值的文章主要介绍了Vue3 中 keepAlive 如何搭配 VueRouter 来更自由的控制页面的状态缓存?。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

在 vue 中,默认情况下,一个组件实例在被替换掉后会被销毁。这会导致它丢失其中所有已变化的状态——当这个组件再一次被显示时,会创建一个只带有初始状态的新实例。但是 vue 提供了 keep-alive 组件,它可以将一个动态组件包装起来从而实现组件切换时候保留其状态。本篇文章要介绍的并不是它的基本使用方法(这些官网文档已经写的很清楚了),而是它如何结合 VueRouter 来更自由的控制页面状态的缓存

全部缓存

我们先搭建一个 Vue 项目,里面有三个页面a,b,c,并给它们一些相互跳转的逻辑和状态

  • a 页面
<template>
  <div>
    <div>A页面</div>
    <input type="text" v-model="dataA" /><br />
    <div @click="toB">跳转B</div>
    <div @click="toC">跳转C</div>
  </div>
</template>

<script lang="ts" setup>
import { ref } from "vue";
import { useRouter, useRoute } from "vue-router";
const router = useRouter();
const route = useRoute();
const dataA = ref("");
const toB = () => {
  router.push("/bb");
};
const toC = () => {
  router.push("/cc");
};
</script>
  • b 页面
<template>
  <div>
    <div>B页面</div>
    <input type="text" v-model="dataB" /><br />
    <div @click="toA">跳转A</div>
  </div>
</template>

<script lang="ts" setup>
import { ref } from "vue";
import { useRouter } from "vue-router";
const router = useRouter();
const dataB = ref("");
const toA = () => {
  router.push("/aa");
};
</script>
  • c 页面
<template>
  <div>
    <div>C页面</div>
    <input type="text" v-model="dataC" />
    <div @click="toA">跳转A</div>
  </div>
</template>

<script lang="ts" setup name="C">
import { ref } from "vue";
import { useRouter } from "vue-router";
const router = useRouter();
const dataC = ref("");
const toA = () => {
  router.push("/aa");
};
</script>

然后在 route/index.ts 写下它们对应的路由配置

import { createRouter, createWebHashHistory, RouteRecordRaw } from "vue-router";

const routes: RouteRecordRaw[] = [
  {
    path: "/aa",
    name: "a",
    component: () => import(/* webpackChunkName: "A" */ "../views/a.vue"),
  },
  {
    path: "/bb",
    name: "b",
    component: () => import(/* webpackChunkName: "B" */ "../views/b.vue"),
  },
  {
    path: "/cc",
    name: "c",
    component: () => import(/* webpackChunkName: "C" */ "../views/c.vue"),
  },
];

const router = createRouter({
  history: createWebHashHistory(),
  routes,
});

export default router;

在 App.vue 中我们用 keep-alive 将 router-view 进行包裹

<template>
  <keep-alive>
    <router-view />
  </keep-alive>
</template>

启动项目,测试一下页面状态有没有被缓存

Vue3 中 keepAlive 如何搭配 VueRouter 来更自由的控制页面的状态缓存?

此时我们发现状态并没有缓存,并且控制台还给了个警告

Vue3 中 keepAlive 如何搭配 VueRouter 来更自由的控制页面的状态缓存?

上面的写法在 vue2 中是可以的,但是在 vue3 中需要将 keep-alive 写在 router-view 中才行,我们修改一下写法

<template>
  <router-view v-slot="{ Component }">
    <keep-alive>
      <component :is="Component" />
    </keep-alive>
  </router-view>
</template>

这种写法其实就是 router-view 组件的插槽传递了一个带有当前组件的组件名 Component 的对象,然后用 keep-alive 包裹一个动态组件(回归原始写法)。

我们再试一下页面的缓存效果,这时候发现页面的状态被缓存了

Vue3 中 keepAlive 如何搭配 VueRouter 来更自由的控制页面的状态缓存?

缓存指定页面

通常情况下我们并不想将所有页面状态都缓存,而只想缓存部分页面,这样的话该怎么做呢?

其实我们可以在 template 中通过$route 获取路由的信息,所以我们可以在需要缓存的页面配置一下 meta 对象,比如 a 页面我们想缓存其状态,可以将 keepAlive 设置位 true

//route/index.ts

const routes: RouteRecordRaw[] = [
  {
    path: "/aa",
    name: "a",
    meta: {
      keepAlive: true,
    },
    component: () => import(/* webpackChunkName: "A" */ "../views/a.vue"),
  },
  ...
];

然后回到 App.vue 中判断 keepAlive 来决定是否缓存

<template>
  <router-view v-slot="{ Component }">
    <keep-alive>
      <component v-if="$route.meta.keepAlive" :is="Component" />
    </keep-alive>
    <component v-if="!$route.meta.keepAlive" :is="Component" />
  </router-view>
</template>

再看下效果

Vue3 中 keepAlive 如何搭配 VueRouter 来更自由的控制页面的状态缓存?

此时我们发现 a 页面状态被缓存,b 页面的状态没有缓存

但是有时候我们想要这样一个效果

a 跳转 b 的时候我们需要缓存 a 页面状态,但是当 a 跳转 c 的时候我们不需要缓存 a 页面,此时我们该如何做呢?

或许有的同学想到了这样一个方法,当 a 跳转 c 的时候将 a 页面的缓存删除,这样就实现了上面的效果。可惜我找了半天也没找到 vue3 中删除指定页面缓存的方法

我也尝试过跳转 c 页面的时候将 a 的 keepAlive 设置为 false,但是再次回到 a 页面的时候 keepAlive 会重置,a 页面状态依然会被缓存。

既然如此为了做到更精细的缓存控制只有使用 keep-alive 中的 inclue 属性了

使用 inclue 控制页面缓存

keep-alive 默认会缓存内部的所有组件实例,但我们可以通过 include 来定制该行为。它的值都可以是一个以英文逗号分隔的字符串、一个正则表达式,或是一个数组。这里我们使用一个数组来维护需要缓存的组件页面,注意这个数组中是组件的名字而不是路由的 name

在 vue3 中给组件命名可以这样写

<script lang='ts'>
export default {
    name: 'MyComponent',
}
</script>

但是我们通常会使用 setup 语法,这样的话我们得写两个script标签,太麻烦。我们可以使用插件vite-plugin-vue-setup-extend处理

npm i vite-plugin-vue-setup-extend -D

然后在vite.config.ts中引入这个插件就可以使用了

import { defineConfig, Plugin } from "vite";
import vue from "@vitejs/plugin-vue";
import vueSetupExtend from "vite-plugin-vue-setup-extend";

export default defineConfig({
  plugins: [vue(), vueSetupExtend()],
});

然后就可以这样命名了

<script lang="ts" setup name="A"></script>

下面我们修改一下 App.vue

<template>
  <router-view v-slot="{ Component }">
    <keep-alive :include="['A']">
      <component :is="Component" />
    </keep-alive>
  </router-view>
</template>

这其实就代表组件名为 A 的 页面才会被缓存,接下来我们要做的就是控制这个数组来决定页面的缓存,但是这个数组要放在哪里维护呢? 答案肯定是放到全局状态管理器中拉。所以我们引入 Pinia 作为全局状态管理器

npm i pinia

在 main.ts 中注册

import { createPinia } from "pinia";
const Pinia = createPinia();
createApp(App).use(route).use(Pinia).use(RouterViewKeepAlive).mount("#app");

新建 store/index.ts

import { defineStore } from "pinia";

export default defineStore("index", {
  state: (): { cacheRouteList: string[] } => {
    return {
      cacheRouteList: [],
    };
  },
  actions: {
    //添加缓存组件
    addCacheRoute(name: string) {
      this.cacheRouteList.push(name);
    },
    //删除缓存组件
    removeCacheRoute(name: string) {
      for (let i = this.cacheRouteList.length - 1; i >= 0; i--) {
        if (this.cacheRouteList[i] === name) {
          this.cacheRouteList.splice(i, 1);
        }
      }
    },
  },
});

在 App.vue 中使用 cacheRouteList

<template>
  <router-view v-slot="{ Component }">
    <keep-alive :include="catchStore.cacheRouteList">
      <component :is="Component" />
    </keep-alive>
  </router-view>
</template>
<script lang="ts" setup>
import cache from "./store";
const catchStore = cache();
</script>

此时就可以根据 cacheRouteList 控制缓存页面了。

此时我们再来实现前面提到的问题a 跳转 b 的时候我们需要缓存 a 页面状态,但是当 a 跳转 c 的时候我们不需要缓存 a 页面就很简单了

import cache from "../store";
const catchStore = cache();
const router = useRouter();

const toB = () => {
  catchStore.addCacheRoute("A");
  router.push("/bb");
};
const toC = () => {
  catchStore.removeCacheRoute("A");
  router.push("/cc");
};

此时再看下页面的效果

Vue3 中 keepAlive 如何搭配 VueRouter 来更自由的控制页面的状态缓存?

可以发现 a 到 c 后再回来状态就重置了,这样不仅做到了上述效果,还可以让你随时随地的去删除指定组件的缓存。

到这里我们便完成了使用 inclue 对页面状态缓存进行更精细化的控制。当然,如果你有更好的方案欢迎在评论区指出,一起讨论探索文章来源地址https://www.toymoban.com/news/detail-668186.html

到了这里,关于Vue3 中 keepAlive 如何搭配 VueRouter 来更自由的控制页面的状态缓存?的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • VUE之VueRouter页面跳转

    参考视频 参考demo及视频资料 VUE之基本部署及VScode常用插件 VUE之基本组成和使用 VUE之Bootstrap和Element-UI的使用 VUE之axios使用,跨域问题,拦截器添加Token

    2024年02月14日
    浏览(34)
  • 补充 vue3用户管理权限(路由控制)

    之前有人问我 ,如果是二级路由如何添加,这里我做一个补充吧。直接拿方法去用就行。也不做解释了。稍微看下就能看懂了 假设,后端返回给我们一个数据 [“/defa”,\\\"/defa/defa1\\\"] 这样的一个路由表,我们就需要通过这个路由表去筛选匹配我们的动态路由,然后在进行添加。

    2024年01月21日
    浏览(49)
  • 记录--Vue的缓存组件 | 详解KeepAlive

    一. keep-alive 的作用 二. keep-alive 的原理 三. keep-alive 的应用 四. keep-alive 的刷新 五. keep-alive 页面缓存思路 首先引用官网文档介绍:keep-alive官方文档 Vue 的 keep-alive为抽象组件,主要用于缓存内部组件数据状态。可以将组件缓存起来并在需要时重新使用,而不是每次重新创建。

    2024年02月09日
    浏览(35)
  • vue3用户权限管理(导航栏权限控制)2

    上一节我们说到,通过后端的用户权限来进行路由的动态添加,实现权限控制,这一节我们通过递归导航栏组件,实现后台权限控制导航栏,接上一节所说我们在vuex中存储了一个路由数组[\\\"/\\\",\\\"*\\\"]进行权限控制,这一节还是要使用这个路由数组进行导航栏的控制,开始吧。  

    2024年02月03日
    浏览(63)
  • VUE3,自定义控制keep-alive缓存

    安装插件 npm install vite-plugin-vue-setup-extend --save 在vite.config.ts中 import VueSetupExtend from \\\'vite-plugin-vue-setup-extend\\\' ..... plugins:[         vue(),         VueSetupExtend(),         ..... ] useKeepalive.ts import { ref } from \\\"vue\\\" export const includes = refstring[]([]); // 增加缓存 export function addKeepAliveC

    2024年01月19日
    浏览(37)
  • 解决vue3使用iconpark控制台预警提示问题

    最近在项目中使用 iconpark-icon 来管理图标,一切都很顺利,引入链接后,图标正常显示,没有报错。但是控制台却发出了预警信息。 [Vue warn]: Failed to resolve component: iconpark-icon If this is a native custom element, make sure to exclude it from component resolution via compilerOptions.isCustomElement. 虽说不

    2024年02月04日
    浏览(53)
  • vue3-element-plus,控制表格多选的数量

    控制表格的多选,最多只能选择5条数据,并且其他项禁用

    2024年02月16日
    浏览(56)
  • vue3 实现门户网站页面鼠标滚轮控制页面上下滚动---类似轮播图

    案例参考:首页_CNESA 储能研究平台 //监听鼠标滚动事件  window.addEventListener(\\\'mousewheel\\\', debounce(methodB,300), true)||window.addEventListener(\\\"DOMMouseScroll\\\",debounce(methodB,300),false) const debounce = (func, wait) ={         let timeout;         return  function() {             let context = this;            

    2024年02月12日
    浏览(80)
  • 【C语言】EOF搭配while循环来控制scanf输入的次数

    目录 EOF是什么? EOF搭配while的实际应用场景1 EOF搭配while的实际应用场景2 补充 后言 EOF , 在C语言的标准函数库中表示 文件结束符 (end of file)。在while循环中以EOF作为文件结束标志,这种以EOF作为文件结束标志的文件,必须是文本文件。 在文本文件中,数据都是以字符的ASC

    2024年02月10日
    浏览(39)
  • 搭配 TypeScript 使用 Vue​

    Volar 是官方的 VSCode 扩展,提供了 Vue 单文件组件中的 TypeScript 支持,还伴随着一些其他非常棒的特性 。 TypeScript Vue Plugin 用于支持在 TS 中 import *.vue 文件。 通过 create-vue 搭建的项目包含了预先配置好的 tsconfig.json。 手动配置 tsconfig.json 时,请留意以下选项: compilerOptions.is

    2024年02月03日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包