Vue.js使用computed监听scrollTop时回到顶部按钮不消失问题
问题根因
Vue 计算属性(computed)的自动重算机制,仅对依赖项中被 Vue 响应式系统托管的状态变更生效。你在计算属性中直接读取的document.documentElement.scrollTop是原生DOM属性,不属于Vue管理的响应式状态,页面滚动导致该值变化时,Vue完全感知不到这个变更,因此visible计算属性只会在组件初始化时执行1次求值,后续滚动过程中不会重新计算,自然无法正确控制按钮显隐。
另外还有个兼容性隐患:部分浏览器的页面滚动偏移挂载在document.body.scrollTop上,仅判断document.documentElement.scrollTop在这类浏览器中会出现取值错误。
修复方案
- 组件内部新增响应式变量存储当前滚动位置,作为计算属性的真实依赖
- 组件挂载时绑定全局
scroll事件监听,每次滚动时同步更新这个响应式的滚动位置值 - 组件卸载时移除绑定的scroll事件监听,避免内存泄漏
- 计算属性基于响应式的滚动位置判断显隐,同时做scrollTop取值的浏览器兼容
修复后完整代码如下:
<template> <button v-show="visible" @click="backToTop">👆</button> </template> <script lang="ts"> export default { data() { return { // 响应式存储当前滚动位置 scrollTop: 0 } }, computed: { visible() { // 依赖响应式scrollTop,值更新时会自动触发重算 return this.scrollTop > 0 } }, mounted() { // 绑定滚动监听 window.addEventListener('scroll', this.handleScroll) // 初始化时同步一次当前滚动位置 this.handleScroll() }, // Vue2.x版本请将beforeUnmount替换为beforeDestroy beforeUnmount() { // 移除监听避免内存泄漏 window.removeEventListener('scroll', this.handleScroll) }, methods: { handleScroll() { // 兼容不同浏览器的scrollTop取值 this.scrollTop = document.documentElement.scrollTop || document.body.scrollTop }, backToTop() { window.scrollTo({ top: 0, behavior: 'smooth' }) } } } </script>
内容的提问来源于stack exchange,提问作者thawne
相关产品推荐
相关产品推荐

