为什么元素的 scrollTop 一直为 0?

简介: 为什么元素的 scrollTop 一直为 0?

最近在开发时,遇到一个理论与实践不相符的问题:明明 div 可以滚动,偏偏获取不到它的 scrollTop。

功能:

1.“返回顶部”按钮默认隐藏;

2.当页面往下滚动到 200px 以后时,“返回顶部”按钮出现。

3.当点击“返回顶部”按钮时,页面滚动到顶部。

草图:


1.jpg


2.jpg


思路:

1.一开始让“返回顶部”按钮隐藏,监听 div 滚动事件,到达指定高度后,让按钮出现。

2.“返回顶部”按钮监听点击事件,点击后,回到 div 顶部即可。


本来是 Vue 代码,懒得启动脚手架,直接写原生演示。

页面结构:可以根据 Vue 单页面想象一下,最外层是元素 app,中间的 container 是某路由渲染的模块内容。

<body>
  <div id="app">
    <div class="container">
      <h1>app 某模块</h1>
      <h2>模块总高度:2000px</h2>
      <p>当前滚动的高度:<span class="current-scrollTop">0</span> px</p>
      <a class="back-top hide" href="javascript:;">返回顶部</a>
    </div>
  </div>
</body>

页面样式:

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}
html,
body {
  height: 100%;
  overflow: hidden;
}
#app {
  height: 100%;
  border: 5px dashed red;
  overflow: auto;
}
#app>.container {
  height: 2000px;
  margin: 0 auto;
  background-color: #abcdef;
}
#app>.container>h1,
#app>.container>h2,
#app>.container>p {
  text-align: center;
}
#app>.container>p {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  font-weight: 700;
}
/* 按钮 */
a.back-top {
  position: fixed;
  right: 50px;
  bottom: 50px;
  display: inline-block;
  padding: 10px;
  text-decoration: none;
  border: 2px solid #000;
}
/* 控制按钮隐藏 */
a.back-top.hide {
  display: none;
}

页面逻辑:

  1. 1.开始犯错
const dom = document.getElementsByClassName('container')[0];
dom.addEventListener('scroll', function () {
  console.log('scrollTop: ', this.scrollTop);
})
console.log(dom.scrollTop); // 0

按照上面的写法,始终没有监听到 div 的滚动事件,打印的 scrollTop 也只有一个 0

  1. 2.明明页面可以滚动,怎么监听不到事件呢?
  2. 3.哦!div.container 根本不能滚动,能滚动的是设置了 overflow: auto; 的 app 元素!
  3. 4.监听 app 元素的滚动事件试一试:
const app = document.getElementById('app');
app.addEventListener('scroll', function () {
  console.log('scrollTop: ', this.scrollTop);
})

成功了,控制台里有数据记录。

  1. 5.接下来根据设计思路,编写正确的代码就行:
const app = document.getElementById('app');
const dom = document.getElementsByClassName('container')[0];
const btn = document.getElementsByClassName('back-top')[0];
const text = document.getElementsByClassName('current-scrollTop')[0];
app.addEventListener('scroll', function () {
  text.innerText = this.scrollTop;
  if (this.scrollTop > 200) {
    btn.classList.remove('hide');
  } else {
    btn.classList.add('hide');
  }
})
btn.addEventListener('click', function () {
  if (app.scrollTop > 200) {
    app.scrollTo({
      top: 0,
      behavior: 'smooth'
    })
  }
})

没错,真相就在这里:由于给 html、body 设置了 overflow: hidden; 属性,视觉上,让我误以为滚动条是 div.container 的,实际上是 #app 的。(当然,Vue 里的代码最好在 unmounted(destroyed) 钩子触发时,将一些事件监听器移除,以免对其他组件造成影响。)



目录
相关文章
|
存储 开发框架 前端开发
从零开始学习前端开发
前端开发是现代互联网应用程序开发中不可或缺的一部分。本文将带您从零开始学习前端开发,包括HTML、CSS和JavaScript等核心技术,以及常见的开发框架和工具。
|
网络协议 安全 网络安全
申请通配符 SSL 证书的详细流程
申请通配符SSL证书需明确需求并选择知名CA,选择通配符证书,提交域名信息,通过DNS或邮件验证域名,下载证书文件及私钥。最后在服务器上配置证书和私钥,调整SSL参数,确保网站安全启用加密,提升用户信任。
|
前端开发 JavaScript Serverless
揭秘CSS布局神器:vw/vh、rem、%与px大PK,掌握它们,让你的网页设计秒变高大上,面试难题迎刃而解!
【8月更文挑战第4天】在Web开发中,合理选择CSS单位对响应式布局至关重要。本文探索viewport单位(vw/vh)、rem、百分比(%)及像素(px)的基础知识与应用场景。通过代码示例,展示如何运用这些单位实现全屏布局、尺寸比例调整、灵活的元素大小及固定尺寸。最后,模拟面试题,介绍如何仅用CSS实现一个元素的高度为其宽度两倍且响应视口变化的方法。
882 8
|
前端开发
React给antd中TreeSelect组件左侧加自定义图标icon
本文介绍了如何在React中为Ant Design的TreeSelect组件的每个树节点添加自定义图标,并解决了因缺少key属性而导致的警告问题,展示了如何通过递归函数处理treeData数据并为每个节点添加图标。
868 2
React给antd中TreeSelect组件左侧加自定义图标icon
|
缓存 JavaScript 前端开发
《基础篇第4章:vue2基础》:使用vue脚手架创建项目
《基础篇第4章:vue2基础》:使用vue脚手架创建项目
440 3
|
JavaScript 前端开发
使用 WebGL 创建 3D 动画
【10月更文挑战第3天】使用 WebGL 创建 3D 动画
|
JavaScript 前端开发 UED
vue中vue-router路由懒加载(按需加载)的作用以及常见的实现方法
vue中vue-router路由懒加载(按需加载)的作用以及常见的实现方法
914 1
Vue3栅格(Grid)
该文章介绍了一种基于24栅格系统的布局方案,通过`Row`和`Col`组件实现灵活的内容排布。`Row`负责水平方向的一组`Col`,`Col`则用于承载实际内容。栅格系统支持1到24的列值,超过24的`Col`会自动换行。此外,系统还支持Flex布局,允许子元素进行多种对齐方式,并可通过响应式属性适应不同屏幕尺寸。文章提供了详细的API说明和代码示例,展示了如何在实际项目中应用这一布局系统。
583 1
Vue3栅格(Grid)
|
前端开发 安全 容器
CSS如何优雅实现卡片多行排列布局?
【8月更文挑战第24天】CSS如何优雅实现卡片多行排列布局?
1068 3
|
JavaScript 前端开发 Shell
实现在vue中自定义主题色彩切换
实现在vue中自定义主题色彩切换
469 0

热门文章

最新文章