vue-router提供了vue路由跳转的功能,有时候我们需要缓存上一个页面,避免重新渲染耗费时间,所以要对一些组件做缓存
keep-alive组件
keep-alive
是vue内置的组件,用来缓存包裹的动态组件,当组件切换时候,不会销毁不活动的组件,他有两个属性include
和 exclude
,可以用来有条件地缓存组件,值可以是逗号分隔的字符串,正则表达式或者一个数组
<!-- 逗号分隔字符串 -->
<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>
匹配首先检查组件自身的 name
选项,如果 name 选项不可用,则匹配它的局部注册名称 (父组件 components 选项的键值)。匿名组件不能被匹配。
<keep-alive> 不会在函数式组件中正常工作,因为它们没有缓存实例。
include实现缓存
本文主要用 include
来实现前进时候组件缓存,后退时候组件销毁的功能
假如我们有一个需求,列表 -> 详情,详情 -> 列表,由于列表可能有查询,分页的功能,不需要销毁而是直接进入详情页面,这样返回就不需要重新生成新的组件导致原有的查询或者分页失效
那么只要在 keep-alive
添加 include
组件名数组,如下,PostList
文章列表组件会缓存,而文章详情就不会被缓存
<keep-alive :include="r">
<router-view></router-view>
</keep-alive>
在data里面声明需要缓存的组件名
data () {
return {
r: ['PostList']
}
}
这样子就解决了两个页面之间的前进加载新页面,后退加载缓存页面的功能
多页面跳转和缓存
如果是多个页面的情况,相对比较复杂点,比如 a->b->c->d,首先记录一下路由的来源,比如 a->b->c,我们需要缓存的是 a和b,可以通过路由定义的 meta 属性来记录
{
path: '/b',
meta: {
from: 'a' // from组件名
},
name: 'bComponent',
component: bComponent
},
{
path: '/c',
meta: {
from: 'b' // from组件名
},
name: 'cComponent',
component: cComponent
}
在初始化 r
属性的时候,默认 a
路由是必须缓存的,初始值为 r = ['a']
,通过监听 $route
属性来动态设置 keepAlive
的 include
属性值
watch: {
$route (newRoute, oldRoute) {
let newRouteName = newRoute.name, // 新的路由名称
newRouteFrom = newRoute.meta.from;// 新的路由来源
let oldRouteName = oldRoute.name; // 旧的路由名称
if (newRouteName && newRouteFrom && oldRouteName) {
if (newRouteFrom.toLowerCase() === oldRouteName.toLowerCase()) {
// 新的路由来源和旧的路由名称相同,新的组件就缓存
this.r.push(newRouteName)
} else {
// 否则弹出
let removeCmp = this.r.pop();
}
} else {
// 防止home组件缓存被弹出
if (this.r.length > 1) {
let removeCmp = this.r.pop();
}
}
}
}
如果在 /b
路由的时候手动刷新页面,那么需要从 b
开始缓存,一般在最后一个路由的时候是不需要缓存的,所以在 created
或者 mounted
钩子函数里面判断
created () {
// 刷新进入中间路由的情况
if (this.$route.name !== 'a' && this.$route.name !== 'd') {
this.r.push(this.$route.name);
}
}