1,问题的提出
采用vue做手机评分页面的前端,页面显示多个评分项的分数和总分。
每个评分项有个修改按钮,按下后弹出新的页面,用户填写分数后按提交按钮,则保存数据、关闭页面、回到前一页。
此时,页面上显示的分数和总分会刷新,但是显示的页面位置未保留修改前的位置,而是回到了顶部显示。
这种情况如果页面上的分数项多的话,每次填完一项分数,就要下拉一次页面才能回到原来修改分数的位置,继续修改下面的分数,对用户来说非常不便。
那么,有没有办法返回前一页时显示的是离开前的位置呢?
2,走过的弯路
从网上查阅资料,提供了以下思路:离开页面时记住页面位置,回到页面时将位置设置回原来的位置。
结果实践证明是不能成功。但严格来说,可以成功50%,上面前半句可行,后半句不可行。
以下是采用beforeRouteLeave事件记住当前位置,可以取得当前页面的垂直偏移位置:
beforeRouteLeave(to, from, next) { this.$alert(`滚动位置:${document.documentElement.scrollTop} || ${document.body.scrollTop}`); sessionStorage.setItem('scrollTop', document.documentElement.scrollTop || document.body.scrollTop); next(); },
但是,在返回页面的mounted事件中设置scrollTop,却始终是无效的。
以下是我曾经的尝试。无论是设置document.body.scrollTop,还是设置document.documentElement.scrollTop,还是设置window.pageYOffset,统统无效。
通过this.$nextTick或setTimeout延时设置也无效。
通过页面主div设置其scrollTop,也一样无效。
mounted() { // let a= sessionStorage.getItem('scrollTop'); // // this.$alert(a+",mounted,"+document.documentElement.scrollTop); // // this.$alert("1"); // document.body.scrollTop = 5000; // document.documentElement.scrollTop = 4000; // window.pageYOffset = 7000; // // let that=this; // this.$nextTick(()=>{ // setTimeout(()=> { // let mainDiv = that.$refs.mainDiv; // mainDiv.scrollTop = 1000; // // document.body.scrollTop = 500; // // document.documentElement.scrollTop = 400; // // window.pageYOffset = 700; // that.$message.info("$nextTick,"+document.body.scrollTop); // }, 13) // // }) // this.$message.info(a+",mounted,"+document.body.scrollTop); },
3,有效的方案
显然,不是上述方案不正确,而是上述方案不适用于vue前端。
经过查找资料,以下文章(以下简称原文)给出了可行方案:
https://blog.csdn.net/sinat_41694829/article/details/116018702
上述方案的思路是2点:用keepAlive缓存页面及记忆上次浏览位置,以及用activated刷新页面数据。
具体来说,包含以下3步:
第一步,修改app.vue
对于需缓存的页面,用<keep-alive>标签包裹。
<template> <div id="app"> <keep-alive> <router-view v-if="isRouterAlive && $route.meta.keepAlive"></router-view> </keep-alive> <router-view v-if="isRouterAlive && !$route.meta.keepAlive"></router-view> </div> </template>
第二步,修改router\index.js
将需要缓存的页面,在路径特性中申明keepAlive属性。
{ path: '/m_TargScore_Score/:openId/:months', name: 'm_TargScore_Score', component: m_TargScore_Score, meta: { keepAlive: true } },
第三步,修改缓存页面的activated事件
在该事件中刷新页面数据。
activated() { this.initTargData(); },
原文还提出要在Router中加上 scrollBehavior事件以及判断页面是否为第一次加载,但本人实测以上三步就够了。
4,总结
原文中指出,本方案的关键在于vue 的生命周期和路由钩子的相关知识点。
不使用 keep-alive 时
beforeRouteEnter --> created --> mounted --> destroyed
使用 keep-alive 时
beforeRouteEnter --> created --> mounted --> activated --> deactivated
再次进入缓存的页面,只会触发beforeRouteEnter -->activated --> deactivated 。created和mounted不会再执行。
因此对于缓存的页面,刷新数据操作要放在activated 事件中执行。
在此感谢原文作者!
标签:返回,body,vue,--,scrollTop,mounted,document,页面 From: https://www.cnblogs.com/jackkwok/p/17582474.html