带你看懂Vue3 KeepAlive 及实际应用

带你看懂Vue3 KeepAlive 及实际应用

前言

在整理前端知识时,觉得vue3的keepAlive使用上与vue2略有不同,并且vue3可以通过自定义Hooks更好更方便地使用keepAlive。因此决定写一篇博客来记录和讲解下这个我们开发中一定会遇到的知识点。

keepAlive的概念

keepAlive是vue中的一个内置组件,它的功能是在多个组件间动态切换时缓存被移除的组件实例,简单理解就是,当我们路由切换到新的路由再切换回来后,原来的页面能保持原本的实例,并不会被销毁。也就是不会再次触发createmounted这些生命周期钩子函数,取而代之的是onActivatedonDeactivated两个钩子函数,具体用法将在后面讲解。

基本使用

keepAlive上的prop共有三个参数include、exclude、max,具体使用示例如下 (1)include被包涵的组件将能够被缓存

xml 复制代码
<!-- 以英文逗号分隔的字符串 -->
<KeepAlive include="a,b">
  <component :is="view" />
</KeepAlive>

<!-- 正则表达式 (需使用 `v-bind`) -->
<KeepAlive :include="/a|b/">
  <component :is="view" />
</KeepAlive>

<!-- 数组 (需使用 `v-bind`) -->
<KeepAlive :include="['a', 'b']">
  <component :is="view" />
</KeepAlive>

它会根据组件的 name 选项进行匹配,所以组件如果想要条件性地被 KeepAlive 缓存,就必须显式声明一个 name 选项
在 3.2.34 或以上的版本中,使用 <script setup> 的单文件组件会自动根据文件名生成对应的 name 选项,无需再手动声明。

(2)exclude 所包涵的组件将不会被缓存 (3)max 最多可以缓存多少个组件实例

ruby 复制代码
<KeepAlive :max="10">
  <component :is="view"></component>
</KeepAlive>

高级用法

上面我们已经介绍过了keepAlive的基本使用场景,但是在实际应用中,我们更多地是与路由组件相结合来使用,那么具体怎么用呢?

(1)首先我们在定义路由时需要在路由配置中加入配置项,判断当前路由是否需要被缓存。

css 复制代码
 {
        path: '/',
        name: 'home',
        meta: {
            keepAlive: true,
            deepth:1,
        },
        component: () => import('@/pages/home/home.vue'),
    },

(2)在app.vue中修改router-view的配置,增加keep-alive,通过上面路由中的meta值来判断当前组件是否需要缓存。

ini 复制代码
 <router-view v-slot="{ Component }">
    <keep-alive :include="includeRoute">
        <component
            :is="Component"
            :key="$route.name"
            v-if="$route.meta.keepAlive"
        />
    </keep-alive>
    <component
        :is="Component"
        :key="$route.name"
        v-if="!$route.meta.keepAlive"
    />
</router-view>

(3)通过deepth判断includeRoute中需要被缓存的页面,及时销毁无需缓存的页面。同过比对deepth,也就是页面路由的深度,这样当返回到最外层路由时,可以销毁掉深层次的无用的页面缓存。

ini 复制代码
//keepAlive路由数组
let pathDeepArr: any = [];
// 监听当前路由的name变化
watch(
    () => router.currentRoute.value,
    (newValue: any) => {
        if (newValue.meta.keepAlive) {
            let pathArr = pathDeepArr.filter((item: any) => {
                return item.name == newValue.name;
            });
            //去重,存在就不添加
            if (pathArr.length == 0) {
                pathDeepArr.push({
                    name: newValue.name,
                    deepth: newValue.meta.deepth,
                });
            }

            let tempArr = pathDeepArr.filter((item: any) => {
                return (
                    item.deepth < newValue.meta.deepth ||
                    item.deepth == newValue.meta.deepth
                );
            });
            pathDeepArr = tempArr;
            includeRoute.value =
                tempArr.length > 0
                    ? tempArr.map((item: any) => item.name)
                    : ['home'];
        }

        if (newValue.name == 'login') {
            includeRoute.value = [];
        }
    },
    { immediate: true },
);

通过上面的步骤,就能将keep-alive与路由完美的结合,那么还有个问题,比如我们在访问列表页时,页面发生了滚动,当我们点击列表中的某一条进入到详情页再返回后,会发现虽然页面被缓存了,数据也都在,但是滚动条到位置跑到了最顶端,那么我们该如何解决这个问题呢?接下来我将用一个hooks解决这个问题。

自定义Hooks

上面提到了keepalive多了两个生命周期的钩子onActivatedonDeactivated,那么我们就可以在页面滚动的时候记住滚动的距离scrollTop,当页面返回,也就是onActivated的时候,滚动到上次滚动到位置。

hooks代码如下:

ini 复制代码
import { ref, onActivated } from 'vue';
const keepAliveHook = () => {
    const scrollRef = ref<any>(null);
    const scrollTop = ref(0);
    //再次返回页面时保持原先滚动的位置
    onActivated(() => {
        scrollRef.value.scrollTop = scrollTop.value;
    });
    //页面滚动保留滚动高度
    const onScrollBody = () => {
        scrollTop.value = scrollRef.value.scrollTop || 0;
    };

    return { onScrollBody, scrollRef };
};

export default keepAliveHook;

在页面中使用:

xml 复制代码
<template>
 <div class="home-container" ref="scrollRef" @scroll="onPageScroll">
 </div>
 </template>

<script lang="ts" setup>
import keepAliveHook from '@/hooks/keepAliveHook';

const { onScrollBody, scrollRef } = keepAliveHook();
//页面滚动
const onPageScroll = () => {
    onScrollBody();
}
</script>

这样就能解决返回页面时无法自动滚动到上次位置到问题了。

最后

以上是我在vue中使用keepalive的一些应用场景,以及经验总结,欢迎掘友们提出更好更多其他用法😊

相关推荐
崔庆才丨静觅6 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60616 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了6 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅7 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅7 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅7 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment7 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅8 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊8 小时前
jwt介绍
前端
爱敲代码的小鱼8 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax