移动端 h5页面经常会遇到 ,希望用户从当前页面往下滚动一段距离后点击进入其他页面,然后返回当前页面,用户看到的应该还是点击进去前的位置,并且不需要重新刷新数据。
vue中可以使用 keep-alive
组件来使用,keep-alive
组件的使用方式这里不做详细说明,具体可以看这里:
vue keep-alive 组件使用方式详解
这里要解决,首先在keep-alive
可用的前提下,实现 : 页面后退不刷新数据并且记住上次滚动位置
第一步:
配置页面为keep-alive页面 ,详细参考上边链接
这里有会几个问题:
1.确实再次进入页面不在刷新数据了,但如果多个入口,比如是个详情页,随着url参数的变化实际还需要刷新数据,但仅配置keep-alive会出现只有首次打开时会加载数据,当然我们可以将数据加载的方法写在active钩子函数中。
但我们这里不想让它每次进来都刷新数据,我们只需要他首次进刷新数据,返回到keep-alive的页面不刷新数据。
这样我们需要让它每次前进 进入该页面的时候都是首次进入,会调created钩子函数刷新数据,但从其他页面返回到keep-alive页面时保留上次进来时加载的数据。
实现方式如下:
1) 首先确保每次正向进入都是 新的页面/新的vue实例 ,这样每次都会调created钩子加载数据
这里提供一种方式 ,可以在 地址上追加一个routerkey
参数 例如: 地址?id=XXX&routerkey='这里可 以是个时间戳但保证要唯一'
这样每次正向进入keep-alive
的页面,实际都是进了不同的地址,也产生了新的vue实例,会重新走实例创建的那一套钩子函数
可以保证每次正向进入都刷新页面
2)当keep-alive
页面中点击链接跳到其他页面后,再返回因为routerkey
还是之前的所以还会展示之前实例的内容,但是还会有一个问题:数据没有刷新,但是页面照常重新渲染,看到的还是例如我们首次进入的内容。
但这里别忘了我们的初衷
,我们是要返回时,之前滚动浏览到哪里这里依然要看到上次的位置。
这里我们需要做两个比较特别的操作
:
首先 当路由离开keep-alive页面时我们要记住离开前页面滚动到的 scrollTop
其次 进入 keep-alive 页面时 我们要让页面滚动到上次浏览的位置
这里我们会用到两个vue的钩子函数 beforeRouteLeave
以及 activated
首先在beforeRouteLeave
中记录离开前的滚动距离,这里直接上代码,不做额外讲解了
beforeRouteLeave(to, from, next) {
if (from.meta.keepAlive) {
// 只针对 keep-alive 的页面记录滚动位置
let $content = document.querySelector('#根容器 id'); // 列表的外层容器
let scrollTop = $content ? $content.scrollTop : 0;
from.meta.scrollTop = scrollTop;
}
next();
},
这里将 记录的滚动距离 scrollTop
直接记录到了 路由配置中,这里实现方案在我的其他博客中有,不懂可以直接咨询。
然后 当页面进入keep-alive
页面时会调用activated
钩子函数,我们把页面滚动到上次浏览位置的操作可以放在这里实现,也是直接上代码:
activated() {
let scrollTop = this.$route.meta.scrollTop;
if (scrollTop && scrollTop !== 0) {
// 初次进入页面不执行,返回页面执行
let $content = document.querySelector('#根容器 id');
if ($content) {
this.$nextTick(() => {
$content.scrollTop = scrollTop;
})
}
}
}
这个方法主要要注意的一点是 首先为了性能的优化 ,滚动距离为 0
的就不再走下面逻辑,其次滚动放在页面渲染完成 ,使用 vue的 $nextTick
函数,这个函数的具体用法参考我的其他博客。
这两个方法也可以通过mixins
混入的方式混入到所有页面,但这样主页性能上的问题,尽可能判断只在keep-alive页面上生效。
这样前进刷新页面,后退不刷新页面,记录上次滚动位置就实现了。
但这里还有个问题:出于性能的考虑,由于路由加上routerkey,每次访问keep-alive页面都会重新生成一个vue的实例,当浏览次数多时会造成累积了很多未销毁实例,影响页面性能
这里 vue提供了一个$destroy
方法用于销毁vue实例,但这个方法存在一个严重问题,当用$destroy
销毁了keep-alive页面后,销毁掉的页面永远不在会被缓存。所以这个方法并不可用,这里有替代这个方法的方案,但时间仓促,后续博客会针对讲解,请见谅。
本次内容如有不全或者疑惑的地方欢迎评论或者私信了解。