Vue里返回时缓存数据并滚动到列表信息

缓存数据

两种方案,一种使用react思想,将搜索条件放入VUEX内,进入页面后重新调取,第二种使用keep-alive,本文采用keep-alive方案。

使用keep-alive的include进行缓存。

使用过另外一种古老的方案,此方案的缺点是第一次进入由于没有走缓存内的路由,所以返回时无法使用缓存,第二次后才正常,所以放弃了。

1
2
3
4
<keep-alive>
<router-view v-if="!xxx"></router-view>
</keep-alive>
<router-view v-if="xxx"></router-view>

目前能用方案,在进入二级页面前将当前页面的name加入到缓存数组。
此name为组件内的name,规范后与路由中的name相同。

xxx.vue

1
name: 'order_list',

由于可能在详情里进行操作,改变一级页面的显示数据,比如状态等等,所以使用用了keep-alive后新增的生命周期重新获取一次列表。
相当于只缓存搜索条件。
Vue页面内不再使用created

xxx.vue

1
2
3
activated() {
this.getBookbagList();
},

max是为了避免过多缓存,key保证不匹配无name属性的组件

Home.vue

1
2
3
4
5
6
7
8
9
10
11
<keep-alive :include="$store.state.keep_alive_route || key + ''" :max="1">
<router-view></router-view>
</keep-alive>

computed: {
key() {
return this.$route.name !== undefined
? this.$route.name + new Date().getTime()
: this.$route.name + new Date().getTime();
}
}

router.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 路由配置
{
path: "/order/order_list",
name: 'order_list',
component: order_list,
meta: {
keepAlive: true,
},
props: true,
},

router.beforeEach((to, from, next) => {
// 项目的一级页面都是两个`//`表示的路由name,所以只要大于两个,则一定为二级页面。
if (((to.fullPath.split('/')).length - 1 > 2 && from.meta.keepAlive)) {
// 进入二级页面时缓存,将name放入缓存数组
store.commit('keep_alive_route', [`${from.name}`])
} else if ((from.fullPath.split('/')).length - 1 > 2) {
// 从二级以上页面返回时不清空缓存的组件name
} else {
store.commit('keep_alive_route', [])
}
next()
})

VUEX

store.js

1
2
3
4
5
6
7
8
state = {
keep_alive_route: []
}
mutations = {
keep_alive_route: (state, data) => {
state.keep_alive_route = data
},
}

返回页面定位

另外一个需求是使用上面的方式返回后,想定位到进入前的那一条数据里。
在路由进入前,保存那条数据的唯一id,在返回后定位过去。
写了一个mixin,引入即可

mixin.scrollIntoView.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
/* 
订单详情返回后定位到那条数据
import { scrollIntoView } from '@/mixin/scrollIntoView';
mixins: [scrollIntoView],

页面上给定位地址标签,用p标签包裹,因为定位会找到td那一栏
:id="scope.row.xxxid"
添加定位属性字段名
scrollintoIdName: 'xxxid'
获取列表时
this.scrollIntoView()
*/

const scrollIntoView = {
methods: {
scrollIntoView() {
setTimeout(() => {
try {
document.getElementById(this.$store.state.page_id).parentNode.parentNode.scrollIntoView()
this.$store.commit('route_from_name', '')
this.$store.commit('page_id', '')
} catch (error) {
// 不处理错误
return
}
}, 100);
},
},
beforeRouteLeave(to, from, next) {
if (to.params[this.scrollintoIdName]) {
this.$store.commit('page_id', to.params[this.scrollintoIdName])
}
next()
}
}

export {
scrollIntoView
}

store.js

1
2
3
4
5
6
7
8
state = {
page_id: ''
}
mutations = {
page_id: (state, data) => {
state.page_id = data
},
}