vue3中KeepAlive使用

1,428 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第15天,点击查看活动详情

​ keepAlive是Vue的内置组件,作用是将组件缓存在内存当中,防止重复渲染DOM,属于空间换时间的方式。配置了keepAlive的路由或组件,只会在页面初始化的时候执行 created -> mounted 生命周期,第二次及以后再进入该页面将不再执行这段生命周期,而会直接去读取缓存信息。

​ 被 keepAlive 包裹的组件和页面,激活时的声明周期为:created -> mounted -> activated

​ 其中 created -> mounted 是第一次进入时才会执行,activated 在每次激活时都会执行,属于 keepAlive 的一个特定的生命周期,

deactivated:组件离开时触发

使用方式

方式一:路由配置

1、App.vue文件

<template>
  <router-view v-slot="{ Component }">
    <!-- 路由的meta信息中,设置了keepAlive为true的路由将会被缓存 -->
    <keep-alive>
      <component :is="Component" v-if="$route.meta.keepAlive" :key="route.name"  />
    </keep-alive>
    <!-- 没设置keepAlive的路由就是默认的路由 -->
    <component :is="Component" v-if="!$route.meta.keepAlive" :key="route.name"  />
  </router-view>
</template>

2、添加 keepAlive 属性

  • 添加三个测试页面:a、b、c
// router.ts
const routes: Array<RouteRecordRaw> = [
  {
    path: "/a",
    name: "a",
    meta: {
      keepAlive: true
    },
    component: () => import("~/pages/a.vue"),
  },
  {
    path: "/b",
    name: "b",
    meta: {
      keepAlive: true
    },
    component: () => import("~/pages/b.vue"),
  },
  {
    path: "/c",
    name: "c",
    component: () => import("~/pages/c.vue"),
  },
];

3、修改 a、b、c三个组件

<template>
  <div>
    a
    <button @click="jump('/b')">跳转b</button>
    <button @click="jump('/c')">跳转c</button>
  </div>
</template>

<script lang="ts">
import { defineComponent, onActivated, onMounted } from "vue";
import { useRouter } from "vue-router";
export default defineComponent({
  setup() {
    const route = useRouter();
    onMounted(() => {
      console.log("a mounted");
    });
    onActivated(() => {
      console.log("a activated");
    });

    const jump = (path: string) => {
      route.push({ path });
    };

    return { jump };
  },
});
</script>

b和c组件类似

4、测试结果

  • 起始页面为 a,输出:a mounted -> a activated
  • 跳转页面 b,输出:b mounted -> b activated
  • 跳转页面c,输出:c mounted -----页面c不是 keepAlive组件,故没有 activated 生命周期
  • 跳转页面a,输出:a activated
  • 跳转页面b,输出:b activated
  • 跳转页面c,输出:c mounted

5、动态设置路由 keepAlive 属性

​ 我们用完 keepAlive 缓存之后,如果想让当前页面或者下一个页面不再缓存(不存在于keepAlive中),可以在 beforeRouteEnter、beforeRouteUpdate、beforeRouteLeave中操作。

export default defineComponent({
  setup() {
    // ...
  },
  beforeRouteLeave(to, from, next) {
    // 设置下一个路由的meata
    to.meta.keepAlive = false
    // 设置当前路由的meta
    from.meta.keepAlive = false
    next() // 进行下一步
  }
});

方式二:组件配置缓存

​ 有些时候我们仅需要缓存页面中的某些组件,或者是在使用动态组件 component 进行组件切换的时候对组件进行缓存

<script setup lang="ts">
import { ref } from "vue";
import aComp from "./a.vue";
import bComp from "./b.vue";
  
const component = ref(true);
const change = () => {
  component.value = !component.value;
};
</script>

<template>
  <div>
    <button @click="change">切换</button>
    <keep-alive>
      <aComp v-if="component" />
      <bComp v-else />
    </keep-alive>
  </div>
</template>