• Vue Router 路由动态缓存组件



    一、简介

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

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

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

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

    基本用法

    <keep-alive>  
      <component :is="currentTabComponent">component>  
    keep-alive>
    
    • 1
    • 2
    • 3

    在上面的例子中,currentTabComponent 是一个动态组件,它的值会根据当前选中的标签页而变化。
    使用 后,当切换标签页时,之前的组件实例会被缓存起来,而不是被销毁。

    生命周期钩子

    包裹的组件拥有两个特有的生命周期钩子: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
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    三、缓存组件

    1. 通过 :include 属性实现

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

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

    vue2.x中

    通过 :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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    .

    vue3.x中

    在 Vue 3 中同样可以使用 :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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48

    2. 通过 v-slot 功能实现

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

    <template>
        <div id="app">
            <router-view v-slot="{ Component }">
                <keep-alive v-if="Component.meta && Component.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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

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

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


    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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    四、注意事项

    • 虽然 可以提高性能,但也要避免过度使用,因为缓存的组件实例会占用内存。

    • 当组件被 包裹时,它的 createdmounted 钩子只会在第一次渲染时调用,之后的切换不会再次触发这两个钩子。

    • 如果需要强制刷新缓存的组件,可以通过改变 key 属性或者使用 ·include/exclude· 属性来动态控制哪些组件需要被缓存。

  • 相关阅读:
    重装系统会影响到电脑的正常使用吗
    【Python】逆向与爬虫的故事
    CSS旋转、缩放、渐变
    linux文件组 avc: denied { dac_read_search } for capability=2
    mysql将id重新修改为递增
    java计算机毕业设计支部党建工作源码+数据库+系统+lw文档+mybatis+运行部署
    Mac下Qt设置应用程序名称--多国语言
    Python 操作redisearch
    【组合递归】【StringBuilder】Leetcode 17. 电话号码的字母组合
    Java18新特性
  • 原文地址:https://blog.csdn.net/x550392236/article/details/137710106