Vue Router路由动态缓存组件使用详解

 更新时间:2025年04月01日 16:20:43   作者:猫老板的豆  
这篇文章主要介绍了Vue Router路由动态缓存组件使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

一、简介

Vue Router 允许你缓存路由组件,这样在用户导航回之前的页面时,组件的状态会被保留而不是重新渲染。这可以通过使用 <keep-alive> 组件来实现。

<keep-alive> 是一个内置抽象组件,它自身不会渲染一个 DOM 元素,也不会出现在父组件链中。

它的主要作用是缓存不活动的组件实例,而不是销毁它们。

当组件在 <keep-alive> 包裹下被切换时,它的状态(包括数据、DOM 结构等)都会被保留,以便在下次重新显示时能够恢复之前的状态,而不是重新创建组件实例。

基本用法

<keep-alive>  
  <component :is="currentTabComponent"></component>  
</keep-alive>

在上面的例子中,currentTabComponent 是一个动态组件,它的值会根据当前选中的标签页而变化。

使用 <keep-alive> 后,当切换标签页时,之前的组件实例会被缓存起来,而不是被销毁。

生命周期钩子

<keep-alive> 包裹的组件拥有两个特有的生命周期钩子:activateddeactivated

  • activated:当组件被激活时调用,即在 keep-alive 缓存中组件再次可见时被调用。
  • deactivated:当组件被停用时调用,即在 keep-alive 缓存中组件不可见时被调用。

这两个钩子可以帮助你更好地管理组件的状态,比如当组件重新被激活时,你可能需要重新获取数据或者更新视图。

二、定义是否缓存组件

根据路由的 meta 字段中的 keepAlive 属性来决定是否缓存组件。

如果 keepAlive 为 true,则组件会被缓存;否则,它会被缓存。

const routes = [
    {
        path: '/foo',
        component: Foo,
        meta: { keepAlive: true } // 这个组件会被缓存
    },
    {
        path: '/bar',
        component: Bar,
        meta: { keepAlive: false } // 没有设置 meta.keepAlive 或其值为 false,则组件不会被缓存
    }
    // ... 其他路由配置
];

三、缓存组件

1. 通过 :include 属性实现

可利用keep-aliveincludeexclude 属性(include 和 exclude 包含的name 是组件的name不是router name)来设置缓存:

  • include 值为字符串或者正则表达式匹配的组件name会被缓存
  • exclude 值为字符串或正则表达式匹配的组件name不会被缓存

vue2.x中

通过 <keep-alive>:include 属性来实现动态缓存组件

<template>
    <div id="app">
        <keep-alive :include="cachedViews">
            <router-view></router-view>
        </keep-alive>
    </div>
</template>

<script>
    export default {
        name: 'App',
        data() {
            return {
                cachedViews: [] // 存储需要缓存的组件名
            };
        },
        watch: {
            $route(to, from) {
            	// 过滤出需要缓存的组件,即 meta.keepAlive = true 的组件
                const keepAliveComponent = to.matched.filter(record => {
                    return record.meta && record.meta.keepAlive;
                });

                if (keepAliveComponent.length) {
                	// 把需要缓存的组件的name放到cachedViews集合里
                    this.cachedViews = this.cachedViews.concat(keepAliveComponent.map(record => record.name));
                } else {
                    const index = this.cachedViews.indexOf(to.name);
                    if (index > -1) {
                        this.cachedViews.splice(index, 1);
                    }
                }
            }
        }
    };
</script>

vue3.x中

在 Vue 3 中同样可以使用 <keep-alive>:include 属性来实现动态缓存组件:

<template>
    <div id="app">
        <keep-alive :include="cachedViews">
            <router-view></router-view>
        </keep-alive>
    </div>
</template>

<script>
    import { ref, onMounted, watch, onUnmounted } from 'vue';
    import { useRoute } from 'vue-router';

    export default {
        name: 'App',
        setup() {
            const cachedViews = ref([]);
            const route = useRoute();

            const updateCachedViews = () => {
                const keepAliveComponent = route.matched.filter(record => {
                    return record.meta && record.meta.keepAlive;
                });

                cachedViews.value = keepAliveComponent.map(record => record.name);
            };

            onMounted(() => {
                updateCachedViews();
            });

            watch(
                route,
                () => {
                    updateCachedViews();
                },
                { immediate: false }
            );

            onUnmounted(() => {
                // 清理操作,如果需要的话
            });

            return {
                cachedViews
            };
        }
    };
</script>

2. 通过 v-slot 功能实现

由于Vue 3 由于引入了组合式 APIv-slot 功能,有更简洁的方式来实现动态缓存:

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

<script>
    import { defineComponent } from 'vue';

    export default defineComponent({
        name: 'App'
    });
</script>

使用<router-view>v-slot 功能来访问当前路由组件的实例。

然后,我们检查这个组件的 meta.keepAlive 属性来决定是否将其包裹在 <keep-alive> 中。

3. 通过 v-if 来实现

在Vue2和Vue3中都可以使用 v-if="$route.meta.keepAlive" 来判断哪些组件需要缓存,简单粗暴

<template>
    <div id="app">
        <keep-alive v-if="$route.meta.keepAlive">
            <router-view></router-view>
        </keep-alive>
        <router-view v-if="!$route.meta.keepAlive"></router-view>
    </div>
</template>

<script>
    import { defineComponent } from 'vue';

    export default defineComponent({
        name: 'App'
    });
</script>

四、注意事项

  • 虽然 <keep-alive> 可以提高性能,但也要避免过度使用,因为缓存的组件实例会占用内存。
  • 当组件被 <keep-alive> 包裹时,它的 createdmounted 钩子只会在第一次渲染时调用,之后的切换不会再次触发这两个钩子。
  • 如果需要强制刷新缓存的组件,可以通过改变 key 属性或者使用 ·include/exclude· 属性来动态控制哪些组件需要被缓存。

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Vue.js路由实现选项卡简单实例

    Vue.js路由实现选项卡简单实例

    这篇文章主要为大家详细介绍了Vue.js路由实现选项卡简单实例,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-07-07
  • Vue Router嵌套路由(children)的用法小结

    Vue Router嵌套路由(children)的用法小结

    嵌套路由就是父路由里面嵌套他的子路由,父路由有自己的路由导航和路由容器(router-link、router-view),通过配置children可实现多层嵌套,这篇文章主要介绍了Vue--Router--嵌套路由(children)的用法,需要的朋友可以参考下
    2022-08-08
  • 使用Vue创建前后端分离项目的完整过程(前端部分)

    使用Vue创建前后端分离项目的完整过程(前端部分)

    这篇文章主要介绍了使用Vue.js和Node.js搭建一个前端和后端分离的项目,并使用VueCLI3脚手架、axios进行HTTP请求、Vue-router实现前端路由和vuex进行状态管理,需要的朋友可以参考下
    2025-01-01
  • vue 解除鼠标的监听事件的方法

    vue 解除鼠标的监听事件的方法

    这篇文章主要介绍了vue 解除鼠标的监听事件的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-11-11
  • vue父子传值,兄弟传值,子父传值详解

    vue父子传值,兄弟传值,子父传值详解

    这篇文章主要介绍了Vue传值-三种常用传值示例,主要介绍了父组件向子组件进行传值,子组件向父组件传值和非父子组件进行传值,感兴趣的小伙伴们可以参考一下
    2021-11-11
  • 基于element-ui表格的二次封装实现

    基于element-ui表格的二次封装实现

    本文主要介绍了基于element-ui表格的二次封装实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-07-07
  • vue不通过路由直接获取url中参数的方法示例

    vue不通过路由直接获取url中参数的方法示例

    通过url传递参数是我们在开发中经常用到的一种传参方法,但通过url传递后改如果获取呢?下面这篇文章主要给大家介绍了关于vue如何不通过路由直接获取url中参数的相关资料,需要的朋友可以参考借鉴,下面来一起看看吧。
    2017-08-08
  • Vue中如何使用Map键值对传参详析

    Vue中如何使用Map键值对传参详析

    最近在做一个vue的项目,碰到一点关于Map键值对传参的问题,下面这篇文章主要给大家介绍了关于Vue中如何使用Map键值对传参的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2022-08-08
  • Element-UI中el-table如何合并相同单元格

    Element-UI中el-table如何合并相同单元格

    这篇文章主要给大家介绍了关于Element-UI中el-table如何合并相同单元格的相关资料,el-table的组件的可以合并单元格,文中通过示例代码介绍的非常详细,需要的朋友可以参考下
    2023-08-08
  • vue拦截器如何增加token参数

    vue拦截器如何增加token参数

    这篇文章主要介绍了vue拦截器如何增加token参数问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-08-08

最新评论