vue可以通过<keep-alive>元素包裹组件,实现缓存,下次使用时不需要重新创建该组件。但存在一个问题:keep-alive包裹的组件中有滚动元素时,keep-alive不会储存滚动位置。实现后退不刷新主要依据keep-alive组件的activated和deactivated这两个生命周期钩子函数。
vue钩子函数的执行顺序:
不使用keep-alive
beforeRouteEnter --> created --> mounted --> destroyed
vi设计http://www.maiqicn.com 办公资源网站大全https://www.wode007.com
使用keep-alive
初次进入页面,beforeRouteEnter --> created --> mounted --> activated --> deactivated
再次进入缓存的页面,只会触发beforeRouteEnter -->activated --> deactivated。created和mounted不会再执行。
其中,activated在keep-alive组件激活时调用.deactivated在keep-alive组件被停用时调用.
Demo实现了后退不刷新,并且返回时滚动到上次浏览的深度。
该demo中,包含三个链接导航。
home --> pageA --> pageB --> pageC
依次前进,每次前进到一个新页面都需要获取数据,而按下后退键后,
从pageC返回到pageB,pageB不再获取新数据,而是使用之前缓存的数据。
从pageB返回到pageA时,pageA不再获取新数据,而是使用之前的数据。并且当pageA存在滚动条时,返回时会滚动到上次浏览高度。
所以,pageA和pageB需要缓存,pageC不需要缓存。
//router.js
import Vue from 'vue';
import Router from 'vue-router';
Vue.use(Router);
const router = new Router({
mode: 'hash',
routes: [
{
path: '/',
name: 'home',
component: () =>
import('./views/Home.vue'),
meta: {
title: '首页',
keepAlive: false //此组件不需要被缓存
}
},
{
path: '/pageA',
name: 'pageA',
component: () =>
import('./views/pageA.vue'),
meta: {
title: 'pageA',
keepAlive: true,
isBack: false
}
},
{
path: '/pageB',
name: 'pageB',
component: () =>
import('./views/pageB.vue'),
meta: {
title: 'pageB',
keepAlive: true,
isBack: false
}
},
{
path: '/pageC',
name: 'pageC',
component: () =>
import('./views/pageC.vue'),
meta: {
title: 'pageC',
keepAlive: false
}
}
]
});
export default router;
//pageA.vue
<template>
<div class="page-a">
<h1>pageA</h1>
<div>
<div class="item" v-for="item in items" @click="goPageB">
{{ item }}
</div>
</div>
<h1 @click="goPageB">go pageB</h1>
</div>
</template>
<script>
export default {
name: 'PageA',
data() {
return {
msg: "我是PageA页面",
items: Array.from({length:50}, (v,k) => k),
data: "",
scrollTop: 0
};
},
beforeRouteEnter(to, from, next) {
if(from.name == 'pageB'){
to.meta.isBack = true;
}
next();
},
mounted() {
console.log('mounted....');
// this指向组件的实例,$el指向当前组件的DOM元素
const $el = this.$el;
//滚动事件
$el.addEventListener("scroll", () => {
//记录位置
this.scrollTop = $el.scrollTop;
});
},
activated() {
if(!this.$route.meta.isBack){
// 如果isBack是false,表明需要获取新数据,否则就不再请求,直接使用缓存的数据
this.getData();
} else {
//恢复滚动条高度
if(this.scrollTop) {
setTimeout(() => {
this.$el.scrollTop = this.scrollTop;
}, 100);
}
}
// 恢复成默认的false,避免isBack一直是true
this.$route.meta.isBack = false;
},
methods: {
getData() {
// getData方法,模拟从后台请求数据
this.data = "数据";
console.log('get data')
},
goPageB(){
this.$router.push({ path: "/pageB" });
},
back() {
this.$router.push({ path: "/" });
}
},
}
</script>
<style>
.page-a {
height: 100vh;
overflow-y: auto;
}
.item {
margin: 5px;
padding: 10px;
background: #ccc;
}
</style>