在使用基于Vue的单页面富应用的开发中,总会面向这样的产品需求,既从列表页跳转详情页面,返回时需要保存列表页的状态。
这种场景下,若是讲数据写入到全局状态中,总会面临复杂的页面路由判断来清楚和存储页面状态。
keep-alive简介
相较于复杂的全局状态管理,Vue在2.x版本中将keep-alive这一组件属性扩展成了内置的抽象组件<keep-alive>,它自身不会渲染一个 DOM 元素,也不会出现在父组件链中。当组件在 <keep-alive> 内被切换,它的 activated 和 deactivated 这两个生命周期钩子函数将会被对应执行。使得被keep-alive组件包裹的组件的状态得以保留也避免了该组件的重复渲染。
keep-alive组件应用也相当的简单,如下:
<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>
与vue-router的结合
当keep-alive与vue-router结合时,就完全匹配我们页面缓存保存状态以及数据的这一个使用场景了。
<keep-alive>
<router-view>
<!-- 所有路径匹配到的视图组件都会被缓存!-->
</router-view>
</keep-alive>
将router-view作为被keep-alive包裹的组件,默认路由下的所有页面都将被缓存,所有页面的状态都会被保留。
那么大家这个时候就会有个疑问,我并不想保留所有的页面呀,我仅仅是想保留几个业务场景,就像文头那种由列表页进入详情页,再由详情页返回列表页时的状态保留。
vue在keep-alive组件提供了include 和 exclude 属性允许组件有条件地缓存。二者都可以用逗号分隔字符串、正则表达式或一个数组来表示
// 组件 app-rank
export default {
name: 'app-rank',
data () {
return {}
}
}
<keep-alive include="app-rank">
<router-view>
<!-- 只有路径匹配到的视图 app-rank 组件会被缓存!-->
</router-view>
</keep-alive>
当场景稍微复杂,如同级目录之间跳转无需保存状态,仅需在跳转详情页面是保存状态时,这样就需要动态管理keep-alive的缓存。
复杂场景下的keep-alive的使用有一下两种方案
方案一:
<keep-alive :include="includeRoute">
<router-view>
<!-- 只有路径匹配到的includeRoute表达式 组件会被缓存!-->
</router-view>
</keep-alive>
方案二:
路由中router.meta 属性中增加是否缓存页面组件的相应字段,优点是便于管理上下游页面组件的缓存。
{
path: '/',
meta: {
title: '应用排行',
keepAlive: true
},
name:'appRankList',
component: (resolve) => require(['./views/app-rank.vue'], resolve)
}
路由中meta下增加keepAlive的属性,以便于route对象中读取。
<keep-alive>
<router-view v-if="$route.meta.keepAlive"></router-view>
</keep-alive>
<router-view v-if="!$route.meta.keepAlive"></router-view>
这样keep-alive中出现的就是需要缓存的路由页面,当需要在离开页面前改变去往页面的缓存状态时,仅需要在页面中添加beforeRouteLeave
export default {
data() {
return {
};
},
beforeRouteLeave(to, from, next) {
// 设置下一个路由的 meta
to.meta.keepAlive = false;
next();
}
}
综上所述,Vue中页面的缓存无需太复杂的状态管理就可以达到缓存页面状态防止重复渲染的作用。
网友评论