Vue之keep-alive从基础到实战 (vue2\vue3)
直接进入主题
一般使用的到的场景
- 从 详情页 --> 列表页 的时候页面的状态是缓存,不用重新请求数据,提升用户体验
- 有一个可以进行筛选的列表页
List.vue
,点击某一项时进入相应的详情页面,等到你从详情页返回List.vue
时,发现列表页居然刷新了!刚刚的筛选条件都没了!!! - 页面中有大量的canvas、svg等等比较耗费性能的渲染时
例如:”浙江碳普惠“中首页用到了konva、lottie,首页多次切换会产生大量内存占用,于是对首页进行了缓存,但是有个问题是有些数据还是要及时更新,所以用到了
onActivated
这个钩子,在里面进行相关逻辑的处理。
keep-alive是什么
keep-alive
是一个Vue全局组件
keep-alive
本身不会渲染出来,也不会出现在父组件链中keep-alive
包裹动态组件时,会缓存不活动的组件,而不是销毁它们
keep-alive怎么用
keep-alive
接收三个参数:
include
:可传字符串、正则表达式、数组
,名称匹配成功的组件会被缓存exclude
:可传字符串、正则表达式、数组
,名称匹配成功的组件不会被缓存max
:可传数字
,限制缓存组件的最大数量
include
和exclude
,传数组
情况居多
先看下官网使用示例
<!-- 基本 -->
<keep-alive>
<component :is="view"></component>
</keep-alive>
<!-- 多个条件判断的子组件 -->
<keep-alive>
<comp-a v-if="a > 1"></comp-a>
<comp-b v-else></comp-b>
</keep-alive>
<!-- 和 `<transition>` 一起使用 -->
<transition>
<keep-alive>
<component :is="view"></component>
</keep-alive>
</transition>
<!-- 逗号分隔字符串 只缓存组件name为a或者b的组件 -->
<keep-alive include="a,b">
<component :is="view"></component>
</keep-alive>
<!-- 正则表达式 (使用 `v-bind`) -->
<keep-alive :include="/a|b/">
<component :is="view"></component>
</keep-alive>
<!-- 数组 (使用 `v-bind`) -->
<keep-alive :include="['a', 'b']">
<component :is="view"></component>
</keep-alive>
<keep-alive :max="10">
<component :is="view"></component>
</keep-alive>
被keep-alive
包含的组件不会被再次初始化,也就意味着不会重走生命周期函数
但是有时候是希望我们缓存的组件可以能够再次进行渲染,这时Vue
为我们解决了这个问题
被包含在 keep-alive
中创建的组件,会多出两个生命周期的钩子: activated
与 deactivated
:
activated
当keep-alive
包含的组件再次渲染的时候触发deactivated
当keep-alive
包含的组件销毁的时候触发
// vue3 示例
import { onActivated } from "vue";
onActivated(() => {
// do something ...
});
配合router
使用
// router配置
{
path: "/home",
component: () => import("../views/home/index.vue"),
meta: {
title: "首页",
keepAlive: true
}
}
// App.vue
// vue2 示例
<keep-alive>
<router-view v-if="$route.meta.keepAlive"></router-view>
</keep-alive>
<router-view v-if="!$route.meta.keepAlive"></router-view>
// vue3 示例
<router-view v-slot="{ Component }">
<keep-alive>
<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>
动态设置keepAlive属性
// 使用组件内守卫,对离开页面事件做一些操作
// to为即将跳转的路由,from为上一个页面路由
beforeRouteEnter(to, from, next) {
to.meta.keepAlive = true;
// 路由继续跳转
next();
}
删除keep-alive
的方法
beforeRouteLeave:function(to, from, next){
if(to.name=='Login'){
if (this.$vnode && this.$vnode.data.keepAlive){
if (this.$vnode.parent && this.$vnode.parent.componentInstance && this.$vnode.parent.componentInstance.cache){
if (this.$vnode.componentOptions){
var key = this.$vnode.key == null? this.$vnode.componentOptions.Ctor.cid + (this.$vnode.componentOptions.tag ? `::${this.$vnode.componentOptions.tag}` : ''): this.$vnode.key;
var cache = this.$vnode.parent.componentInstance.cache;
var keys = this.$vnode.parent.componentInstance.keys;
if (cache[key]){
if (keys.length) {
var index = keys.indexOf(key);
if (index > -1) {
keys.splice(index, 1);
}
}
delete cache[key];
}
}
}
}
}
// this.$destroy();
next();
},
踩坑点
- vue多级菜单(路由)导致缓存(keep-alive)失效
(在二级路由中配置同样的router-view解决)
转载自:https://juejin.cn/post/7094910768285483039