需求:现有四个页面:分类列表页A,表格列表页B,列表搜索页C,详情页D,需要实现以下链路前进刷新后退缓存
- A—>B—>C
B刷新
C—>B—>AB缓存
- A—>B—>D
B刷新
D—>B—>AB缓存
- A—>C—>D
C刷新
D—>C—>AC缓存
方案一
初始思路以及实现如下:
1、在App.vue中
<keep-alive v-if="$route.meta.keepAlive">
<router-view/>
</keep-alive>
<router-view v-else/>
2、在路由中需要缓存的页面
{
path: "/B",
name: 'B',
component: B,
meta:{
keepAlive: true
}
},
{
path: "/C",
name: 'C',
component: C,
meta:{
keepAlive: true
}
}
3、在要缓存的页面的钩子函数中(缓存页面很多可以使用mixins
)
beforeRouteLeave (to, from, next) {
let links = {
'B': ['C', 'D'],
'C': 'D'
}
// 判断是否开启缓存
from.meta.keepAlive = true
if (links[from.name].indexOf(to.name) === -1) {
from.meta.keepAlive = false
this.$destroy()
}
next()
}
此时发现,当第一次A—>B—>C C—>B—>A
,完全正常,满足需求,但是第二次A—>B—>C C—>B—>A
页面并没有缓存,并且请求了数据。原因是第一次从B->A时给B设置了keepAlive为false,第二次A->B时并没有开启缓存
,修改方案只需要替换上面的第二步
在路由的全局钩子函数中
router.beforeEach((to, from, next) => {
let list = ['B', 'C'] // 存放需要缓存页面路由的name值
if (list.indexOf(to.name) > -1) {
to.meta.keepAlive = true
}
next()
})
方案二
1、在App.vue中
<keep-alive :include="includedComponents" :exclude="excludedComponents">
<router-view/>
</keep-alive>
在computed中
computed: {
includedComponents: state => state.includedComponents,
excludedComponents: state => state.excludedComponents
}
2、在store中
show (state, data) {
state.includedComponents = data
}
3、在要缓存的页面的钩子函数中(缓存页面很多可以使用mixins
)
beforeRouteLeave (to, from, next) {
let links = {
'B': ['C', 'D'],
'C': 'D'
}
if (links[from.name].indexOf(to.name) === -1) { // 不需要缓存
this.$store.commit('show', '')
}
next()
},
activated () {
// 这里的name为页面的name,最好与路由的name一致
this.$store.commit('show', this.$route.name)
}
注意:
- 建议在每个组件内部添加name, include匹配首先检查组件自身的 name 选项,如果 name 选项不可用,则匹配它的局部注册名称 (父组件 components 选项的键值)。匿名组件不能被匹配
- 若将include设置空则每个页面都将会缓存
- exclude的优先级高于include 使用exclude后,activated和deactivated不会被激活