Vue项目中如何在无垂直滚动条页面隐藏滚动到底部按钮
问题原因
现有代码存在两处逻辑缺陷,导致无滚动条时滚到底部按钮无法自动隐藏:
- 父组件
Default.vue的滚动条检测逻辑仅绑定了滚动事件,页面首次加载、窗口尺寸变化时不会触发检测,hasScroll状态计算不准确,无法正确控制组件显隐 - 滚动条检测使用
document.body.offsetHeight计算,在Vuetify布局、不同浏览器环境下容易出现高度计算偏差;同时组件内部没有做显隐兜底,无滚动条时window.scrollY始终为0,isVisible恒为false,导致滚到底部按钮一直显示
修复方案
1. 修正Default.vue的滚动条检测逻辑
- 组件挂载后主动执行一次滚动条检测
- 新增窗口大小变化监听,窗口尺寸改变时重新检测滚动条状态
- 改用
document.documentElement属性计算页面总高度,兼容性更好 - 组件销毁时移除事件监听,避免内存泄漏
修改后代码:
<script> export default { name: "DefaultLayout", data() { return { hasScroll: false }; }, mounted() { // 页面挂载后立即检查滚动条状态 this.hasVerticalScroll() // 监听窗口尺寸变化 window.addEventListener('resize', this.hasVerticalScroll) }, destroyed() { // 组件销毁时移除监听,避免内存泄漏 window.removeEventListener('resize', this.hasVerticalScroll) }, methods: { hasVerticalScroll() { // 改用html元素属性计算,适配Vuetify布局与多浏览器 this.hasScroll = document.documentElement.scrollHeight > window.innerHeight; } } } </script> <template> <v-app dark v-scroll="hasVerticalScroll"> <ScrollToTop v-if="hasScroll"></ScrollToTop> </v-app> </template>
2. 给ScrollToTop.vue增加内部兜底校验(可选,推荐)
在组件内部也增加滚动条检测逻辑,和父组件的控制形成双重保险,即使父组件逻辑异常,无滚动条时按钮也不会展示;同时修复滚到底部的位置计算偏差,确保可以准确到达页面底部。
修改后代码:
<template> <div v-scroll="onScroll" > <v-btn v-if="hasScroll && !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-if="hasScroll && isVisible" 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, hasScroll: false } }, mounted() { this.checkScrollExist() window.addEventListener('resize', this.checkScrollExist) }, destroyed() { window.removeEventListener('resize', this.checkScrollExist) }, methods: { // 内部滚动条存在性检测 checkScrollExist() { this.hasScroll = document.documentElement.scrollHeight > window.innerHeight }, onScroll () { this.checkScrollExist() this.isVisible = window.scrollY > 50 }, toTop () { this.position = window.scrollY window.scrollTo({ top: 0, left: 0, behavior: 'smooth' }) }, toBottom(){ // 优先返回之前的浏览位置,无记录则滚动到页面最底部 let pos = this.position > 0 ? this.position : (document.documentElement.scrollHeight - window.innerHeight) window.scrollTo({ top: pos, behavior: 'smooth' }) }, } } </script>
内容的提问来源于stack exchange,提问作者Gavin Teo Juen
相关产品推荐
相关产品推荐

