解决Vue页面固定滚动位置的处理办法
Vue固定滚动位置处理方案分享
在最近的项目中,我们遇到了一个有趣的问题:Vue的滚动位置不固定。在长沙网络推广的过程中,我发现这个问题还挺常见的,因此想分享给大家,希望能为大家提供一些参考。
问题描述:
在列表页跳转到详情页的场景中,我们经常遇到这样的问题。比如从列表的某一项进入详情页,再返回列表时,我们希望列表的位置固定在之前浏览的那一项,而不是每次都回到顶部。
虽然vue-router中的scrollBehavior可以在history模式下实现这一功能,但我们的项目使用的是hash模式。我们需要自己实现这一功能。
思路很简单:在列表页面监听滚动事件,记录滚动位置。从详情页返回到列表页面时,读取之前的滚动位置。
具体实现如下:
在组件的mounted生命周期钩子中,我们进行如下操作:
1. 初始化时,读取滚动位置并设置(可能存在延迟,所以使用了setTimeout)。
2. 监听滚动事件,每次滚动时保存滚动位置。
在实际操作中,我们遇到了一个问题:每次返回到列表页面,页面都会滚动到顶部。我们尝试打印保存的滚动位置,发现返回的值是0,而不是我们保存的值。
经过排查,我们发现每次路由切换都会触发onscroll事件。这让我们很困惑,因为我们并没有滚动页面,为什么会触发onscroll事件。
我们一开始怀疑是hash值的变化导致的。于是,我们尝试在浏览器中输入一些不存在的路由,并没有发现scroll被触发。这个猜测被排除了。
接下来,我们怀疑是否是vue-router内部绑定了scroll事件。但经过检查,我们并没有发现相关证据。
元素的增加导致页面高度变化,这种变化是否也会触发scroll事件呢?我使用vue-cli新建了一个项目,并添加了两个不涉及增删改查的路由。
在实际操作中,我注意到从foo跳转到bar再返回foo时,foo的滚动条位置仍然停留在我之前滚动的地方。这让我想起了浏览器的一个特性,它自身会记录滚动条的位置。
那么,这是浏览器的行为吗?
详细页面返回列表页面的过程中,列表需要重新渲染。这个过程大致分为两个步骤:首先是返回列表页面,然后是页面渲染。而浏览器的滚动条位置恢复操作,发生在这两个步骤之间。这时就会出现一个问题:如果页面上的数据是动态渲染的,浏览器会发现页面的高度小于或等于视口的高度,这意味着不存在滚动条,此时document.body.scrollTop的值会被设置为0。当数据渲染完成后,你所读取的scrollTop值就可能是0。
另一种情况是,如果页面高度大于屏幕高度,页面高度为n,而由于某些操作,如滚动条位置的变化,导致的pos值为n+x(大于当前的scrollTop最大值),那么document.body.scrollTop的值就会被设置为n。当你的数据渲染完成并开始定位时,就会发现定位不准确。
为了解决这个问题,我们想到了使用vue的keep-alive功能。刚开始使用时,效果确实不错。但也发现了一些问题:列表项目靠前的部分,在往返操作时的定位很准确,但越往后的项目,定位越不准确。直接滚动到列表底部再返回,定位通常会停在第二或第三个列表项目。
这引发了我的思考,我猜测浏览器的滚动位置恢复行为可能与hashchange有关。当hash值发生变化时,浏览器会获取当前页面的document.body.scrollTop值和自己存储的滚动条位置。我们需要更深入地了解这个机制并找到解决方案,以确保在页面渲染完成后能够准确地定位到期望的位置。重构后的文章内容如下:
网页滚动条位置的精准管理:从keep-alive到自定义解决方案
在Web开发中,当我们尝试利用keep-alive功能进行页面滚动条位置的管理时,经常会面临定位不准确的问题。这是由于在hashchange事件处理和页面渲染并行时,有时获取到的文档高度已经渲染了几个元素的高度,导致定位不准。为了解决这个问题,我们需要自己动手重新定位。
解决方案的第一步是绑定scroll事件。我们可以通过一个map对象来记录每个hash值对应的滚动条位置。每当页面滚动时,我们更新这个map。代码如下:
```javascript
var map = {};
window.onscroll = function() {
map[location.hash] = document.body.scrollTop;
};
```
第二步是屏蔽浏览器自动恢复滚动位置的行为带来的影响。在hashchange事件发生时,我们强制将滚动条顶部设置为0,同时在scroll事件中,当滚动条已经在顶部时不进行存储操作。这样确保了我们在记录位置时不受浏览器自动滚动的影响。代码实现如下:
```javascript
window.onhashchange = function() {
document.body.scrollTop = 0;
};
window.onscroll = function() {
if (document.body.scrollTop) {
// 存储位置信息
map[location.hash] = document.body.scrollTop;
} else {
// 处理读取操作,稍后会详细介绍
}
};
```
第三步是在读取操作中设置一个定时任务来判断当前的滚动条位置是否与你保存的位置相同。如果不同,则调整滚动条位置至保存的位置。这个过程需要一些优化,确保用户体验的流畅性。具体实现细节需要进一步开发和完善。代码示例如下:
```javascript
// 部分代码省略...
window.onscroll = function() {
// ...其他代码...
else {
var timer = null;
timer = setInterval(function(){
if (document.body.scrollTop == map[location.hash]) {
clearInterval(timer); // 位置匹配,停止定时器
} else {
document.body.scrollTop = map[location.hash]; // 调整滚动条位置至保存的位置
}
}, 20); // 每20毫秒检查一次
}
};
```
上述代码提供了一个基本的框架,用于实现返回时恢复滚动条位置的功能。在实际应用中还需要更多的优化和细节处理,以确保用户体验的流畅性和准确性。具体实现细节和完整代码请参见相关文档或项目源码。
狼蚁SEO团队提供的技术分享,希望对大家的学习有所帮助,也请大家多多支持狼蚁SEO。请注意在实际开发中根据实际情况进行代码的调整和优化。
网络安全培训
- 解决Vue页面固定滚动位置的处理办法
- vue封装第三方插件并发布到npm的方法
- PHP 接入微信扫码支付总结(总结篇)
- Ajax实现登录案例
- 详解vue-cli快速构建vue应用并实现webpack打包
- MSSQL优化之探索MSSQL执行计划(转)
- javascript实现网页中涉及的简易运动(改变宽高、
- vue的事件绑定与方法详解
- Ajax动态为下拉列表添加数据的实现方法
- PHP 构造函数和析构函数原理与用法分析
- PHP不使用递归的无限级分类简单实例
- ASP开发中数据库文件调用的捷径
- Nginx 配置多站点vhost 的方法
- 浅谈PHP链表数据结构(单链表)
- ASP编程入门进阶(二十):ADO组件之显示数据记
- JS 清除字符串数组中,重复元素的实现方法