JavaScript如何获取当前滚动位置 实现返回顶/底部按钮功能
页面滚动位置获取与双向跳转按钮优化方案
更稳妥的滚动位置获取实现
直接使用window.scrollY存在老旧浏览器兼容问题,覆盖全场景的滚动位置获取写法如下,兼容所有主流浏览器:
getScrollTop() { return window.pageYOffset !== undefined ? window.pageYOffset : (document.documentElement || document.body.parentNode || document.body).scrollTop }
如果你的页面使用局部滚动容器(即滚动条挂载在设置了overflow: auto/scroll的DOM节点而非window上),直接读取对应容器DOM的scrollTop属性即可,不需要全局取window值。
现有代码的问题与修正点
- 滚动监听绑定错误:你当前将
v-scroll指令绑定在包裹按钮的div上,这个div不是滚动容器,指令如果默认监听绑定元素的scroll事件将完全无法触发。建议直接在组件挂载阶段给window绑定防抖后的scroll事件,组件卸载时移除监听,避免内存泄漏。 - 可滚动区域判断不准确:现有逻辑仅判断
document.body.scrollHeight,多数场景下浏览器滚动条挂载在document.documentElement节点上,会出现判断失效的问题。 - 滚动到底部的计算逻辑错误:直接滚到
document.body.scrollHeight会超出页面实际可滚动范围,正确的底部位置应该是「页面总高度 - 视口高度」。 - 冗余语法:代码末尾多写了一个
</script>闭合标签,会触发语法报错。 - 异常场景兼容缺失:如果用户点击返回顶部后,手动向下滚动一段距离,之前记录的position值没有清空,会出现点击向下按钮跳转到旧位置的不符合预期的问题。
优化后完整参考代码
<template> <div v-if="hasVScroll"> <v-btn v-if="!isVisible" fab fixed bottom right color="primary" @click="toBottom" > <v-icon>mdi-arrow-down-bold-box-outline</v-icon> </v-btn> <v-btn v-else fab fixed bottom right color="primary" @click="toTop" > <v-icon>mdi-arrow-up-bold-box-outline</v-icon> </v-btn> </div> </template> <script> export default { data() { return { isVisible: false, position: 0, hasVScroll: false, debouncedScroll: null, debouncedResize: null } }, mounted() { // 初始化滚动条状态判断 this.checkHasScroll() // 绑定防抖后的事件监听 this.debouncedScroll = this.debounce(this.onScroll, 100) this.debouncedResize = this.debounce(this.checkHasScroll, 200) window.addEventListener('scroll', this.debouncedScroll) window.addEventListener('resize', this.debouncedResize) }, beforeUnmount() { // 移除事件监听避免内存泄漏 window.removeEventListener('scroll', this.debouncedScroll) window.removeEventListener('resize', this.debouncedResize) }, methods: { // 通用防抖函数 debounce(func, wait = 100) { let timer = null return (...args) => { if (timer) clearTimeout(timer) timer = setTimeout(() => func.apply(this, args), wait) } }, // 兼容全浏览器的滚动位置获取 getScrollTop() { return window.pageYOffset !== undefined ? window.pageYOffset : (document.documentElement || document.body.parentNode || document.body).scrollTop }, onScroll() { const currentTop = this.getScrollTop() this.isVisible = currentTop > 500 // 用户手动滚动离开顶部区域时清空历史位置记录,避免跳转异常 if (currentTop > 200) this.position = 0 }, toTop() { this.position = this.getScrollTop() window.scrollTo({ top: 0, left: 0, behavior: 'smooth' }) }, toBottom() { const docHeight = Math.max( document.body.scrollHeight, document.documentElement.scrollHeight ) // 有历史记录就回到上次停留位置,无记录则滚动到页面最底部 const targetTop = this.position > 0 ? this.position : docHeight - window.innerHeight window.scrollTo({ top: targetTop, behavior: 'smooth' }) }, checkHasScroll() { const docHeight = Math.max( document.body.scrollHeight, document.documentElement.scrollHeight, document.body.offsetHeight, document.documentElement.offsetHeight ) this.hasVScroll = docHeight > window.innerHeight } } } </script>
内容的提问来源于stack exchange,提问作者Gavin Teo Juen
相关产品推荐
相关产品推荐

