vue详情页回到列表页定位到之前位置(keep-alive)
1、将需要缓存的页面路由加上meta属性:
meta:{keepAlive: true}
2、在app.vue里使用keepalive
将
<router-view></router-view>
改为
<keep-alive> <router-view v-if="$route.meta.keepAlive"></router-view> </keep-alive> <router-view v-if="!$route.meta.keepAlive"></router-view>
3、路由守卫
router.beforeEach((to, from, next) => {if ( ["operationRegistrationAdd"].includes(to.name) && to.query.type === "details" ) { from.meta.keepAlive = true; } else { from.meta.keepAlive = false; } next(); });
如果要用局部守卫的话:
列表页:
beforeRouteLeave(to, from, next) { if ( ['operationRegistrationAdd'].includes(to.name) && to.query.type === 'details' ) { from.meta.keepAlive = true } else { from.meta.keepAlive = false } next() }
详情页:
beforeRouteLeave(to, from, next) { if ( ['operationRegistration'].includes(to.name) && from.query.type === 'details' ) { to.meta.keepAlive = true } else { to.meta.keepAlive = false } next() }
第三步用路由守卫去改变 keepAlive 的值会有bug,
优化一下:
data中声明 key: 0,绑定到组件上,当 key 值发生更改时会触发组件更新
列表页使用 activated 生命周期进行判断,如果是从 add 或 edit 回来那么重新请求接口,并且更改 key 值;路由前置守卫是当从列表页的上一级页面过来时刷新列表页的组件
activated() { this.setTitle() const { type } = this.$route.params if (type === 'add' || type === 'edit') { this.getList()
this.key++ } }, beforeRouteEnter(to, from, next) { if (from.name === 'register') { next((vm) => { vm.key++ }) } next() }
详情页:在路由离开时在目标路由(list)的 params 对象下添加 type 值,前提是 list 路由在进入详情时分别传了对应的 add、edit、details
beforeRouteLeave(to, from, next) { to.params.type = from.query.type // 通过query传来的type next() }
思路:使用 keep-alive 缓存的组件,不会反复的经历 created 就会缓存下当前 list 页面,当 add、edit、details 公用一个页面时,需要传递一个 type 作为区别,在 list 页面中通过 activated 生命周期对 type 进行判断,如果是 add 或 edit 就重新请求接口,重新渲染列表;并且将滚动条的位置置顶,这个是通过改变 key 值,组件重新渲染。同时需要注意从哪个路由跳转到当前列表页的,要对那个路由进行判断,每次进来的时候滚动条都是置顶的。