前端开发必备技能知识笔记-keep-alive(路由缓存)

前言

keep-alive是Vue中一个非常有用的特性,它可以帮助我们避免重复渲染和减少组件的渲染次数,从而提高应用程序的性能。

使用场景

以下是keep-alive的一些常见使用场景:

  • 列表渲染:当我们需要渲染大量的列表时,使用keep-alive可以缓存已经渲染的列表,避免重复渲染和减少组件的渲染次数,从而提高应用程序的性能
  • 组件缓存:当我们需要缓存一些组件,避免重复渲染和减少组件的渲染次数,从而提高应用程序的性能
  • 路由缓存:当我们需要缓存一些路由组件,避免重复渲染和减少组件的渲染次数,从而提高应用程序的性能
  • 状态管理:当我们需要管理一些状态,避免重复渲染和减少组件的渲染次数,从而提高应用程序的性能

总之,keep-alive可以帮助我们提高应用程序的性能,减少不必要的渲染和计算,从而提高用户体验和应用程序的响应速度。

本文讲述的主要是路由缓存的实现原理

特点

keep-alive是Vue提供的一个抽象组件,主要用于保留组件状态或避免重新渲染。

<keep-alive> 包裹动态组件时,会缓存不活动的组件实例,而不是销毁他们。

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

但是 keep-alive 会把其包裹的所有组件都缓存起来。

路由缓存

场景

当我们切换路由时,切出路由组件会销毁,所有列表页进入详情页列表页会销毁,重新回到列表页,列表页组件会重新加载。

原理

把需要缓存和不需要缓存的组件区分开,在组件的路由配置的元信息,meta中定义哪些需要缓存哪些不需要缓存

实现

具体代码如下:

1,定义两个出口 router-view

<keep-alive>
    <!-- 需要缓存的视图组件 -->
  <router-view v-if="$route.meta.keepAlive">
  </router-view>
</keep-alive>

<!-- 不需要缓存的视图组件 -->
<router-view v-if="!$route.meta.keepAlive">
</router-view>

2,在router配置中定义哪些需要缓存哪些不需要缓存

new Router({
    routes: [
        {
            path: '/',
            name: 'index',//首页
            component: () => import('./views/keep-alive/index.vue')
        },
        {
            path: '/list',
            name: 'list',//列表页
            component: () => import('./views/keep-alive/list.vue'),
            meta: {
                keepAlive: true //需要被缓存
            }
        },
        {
            path: '/detail',
            name: 'detail',//详情页
            component: () => import('./views/keep-alive/detail.vue')
        }
    ]
})

按需缓存组件

include参数

keep-alive组件如果设置了 include ,就只有和 include 匹配的组件会被缓存,所以思路就是,动态修改 include 数组来实现按需缓存。

<template>
    <keep-alive :include="include">
        <!-- 需要缓存的视图组件 -->
        <router-view v-if="$route.meta.keepAlive">
        </router-view>
    </keep-alive>

  <!-- 不需要缓存的视图组件 -->
    <router-view v-if="!$route.meta.keepAlive">
    </router-view>
</template>
<script>
export default {
    name: 'app',
    data: () => ({
        include: [],
    }),
    watch: {
        $route(to, from) {
            // 如果 要 to(进入) 的页面是需要 keepAlive 缓存的,把 name push 进 include数组
            if (to.meta.keepAlive) {
                if (!this.include.includes(to.name)) {
                    this.include.push(to.name);
                }
            }
        },
    },
};
</script>

此时我们发现,从详情页返回列表页,列表页真的不再刷新了。

进阶

新的问题又出现了,由于列表页被缓存了,这个时候我从首页,再点击进入某个列表,也不刷新了。完了,点击首页导航应该进入不同的列表页的,也就是说,从首页进入列表组件不应该被缓存的。

解决一下,我们在定义路由时,在meta(元信息)中再加一个字段,这里是deepth字段,代表进入路由的层级,比如首页路由deepth是0.5,列表页是1,详情页是2,如下所示:

new Router({
    routes: [
        {
            path: '/',
            name: 'index',
            component: () => import('./views/keep-alive/index.vue'),
            meta: {
                deepth: 0.5 // 定义路由的层级
            }
        },
        {
            path: '/list',
            name: 'list',
            component: () => import('./views/keep-alive/list.vue'),
            meta: {
                deepth: 1
                keepAlive: true //需要被缓存
            }
        },
        {
            path: '/detail',
            name: 'detail',
            component: () => import('./views/keep-alive/detail.vue'),
            meta: {
                deepth: 2
           }
        }
    ]
})

然后在 app.vue中增加监听器,监听我们进入路由的方向,具体代码如下:

<template>
    <keep-alive :include="include">
        <!-- 需要缓存的视图组件 -->
        <router-view v-if="$route.meta.keepAlive">
        </router-view>
    </keep-alive>

  <!-- 不需要缓存的视图组件 -->
    <router-view v-if="!$route.meta.keepAlive">
    </router-view>
</template>
<script>
export default {
    name: 'app',
    data: () => ({
        include: [],
    }),
    watch: {
        $route(to, from) {
            // 如果 要 to(进入) 的页面是需要 keepAlive 缓存的,把 name push 进 include数组
            if (to.meta.keepAlive) {
                if (!this.include.includes(to.name)) {
                    this.include.push(to.name);
                }
            }
            // 如果 要 form(离开) 的页面是 keepAlive缓存的,
            // 再根据 deepth 来判断是前进还是后退
            // 如果是后退
            if (from?.meta?.keepAlive && to?.meta?.deepth < from?.meta?.deepth) {
                const index = this.include.indexOf(from.name);
                // 后退情况下,移除include数组里面的返回前的路由,保证下次进入的时候这个路由下的页面会刷新
                if (index > -1) {
                    this.include.splice(index, 1);
                }
            }
        },
    },
};
</script>

参考:
Vue组件缓存之keep-alive正确使用姿势
官网keep-alive

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

花姐夫Jun

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值