回到顶部的几种实现方法

714 阅读3分钟

在实现开发中,回到顶部是一个很常见的需求,基本上每个 ui 框架都提供了这个功能,如果开发中需要这个功能,最好是直接使用框架的,毕竟框架的功能都经过了测试,相比自己实现可以避免一些坑。但对于一些小型项目,特别是 h5 网页之类的,为了启动速度,单独引入 ui 框架过于奢侈。本文主要探讨回到顶部的实现方法。


修改scrollTop

   scrollTop是一个可修改的属性, 在chrome浏览器中, 可以通过 document.documentElement.scrollTop 访问和修改, 只要将其值设置为0即可。

   但是, 这个目前还不完美, 设置了这个后,直接就回到顶部了, 很突兀。很自然地我们会想到, 如果把这个过程分为多个阶段, 每个阶段只步进一小段距离, 就可以了。

   因此, 可以写出下面的函数

const scrollToPosition = (distance, time) => {
     // st为函数执行时滚动条到文档顶部的距离
     const st = document.documentElement.scrollTop
     // 需要滑动的距离
     const need = st - distance
     // 循环时间,值越小越耗性能
     const loopTime = 20
     // 循环次数
     let loopCount = time / loopTime
     // 每次步进的距离
     const step = need / loopCount

     const scrollTimer = setInterval(() => {
         if (loopCount > 0) {
             // 此项设置是为了精准定位
             loopCount !== 1 ? document.documentElement.scrollTop -= step : document.documentElement.scrollTop = distance
             loopCount--
         } else {
             clearInterval(scrollTimer)
         }
     }, loopTime)

 }

 const backToTop = () => {
     scrollToPosition(0, 200)
 }
 

在使用过程中, 由于当时的scrollTop可能为小数, 也可能设置的time无法整除, 导致出现了一点小小的偏差。函数执行结束时的scrollTop与目标scrollTop有偏差, 不过不会太大, 通常在10px左右, 因此, 在最后一次不步进直接设置为目标scrollTop, 就可以避免这种偏差。

a 标签锚点定位

   a标签通过设置href, 类似 <a href="#block">a tag</a> 即可使得id为block的div出现在视窗的顶部, 因此可以通过放置于顶部的空div来实现回顶效果。当然, 此时是没有动画效果的, 好在css提供了一个属性 scroll-behavior: smooth;

   以下为MDN的描述

当用户手动导航或者 CSSOM scrolling API 触发滚动操作时,CSS 属性 scroll-behavior 为一个滚动框指定滚动行为,其他任何的滚动,例如那些由于用户行为而产生的滚动,不受这个属性的影响。在根元素中指定这个属性时,它反而适用于视窗。

   我们只需要在需要回到的地方使用这个属性接口, 经过实测, 在普通的html文件中, 在body处设置是无效的, 因此可以指定一个div来模拟文档。

.scroll-box{
    overflow-y: scroll;
    scroll-behavior: smooth;
    height: 100vh;
}

   另外, 在这个容器内, 直接将scrollTop设置为0即document.querySelector('.scroll-box').scrollTop = 0也会触发动画效果。用a标签主要是提供了一种不需要使用JavaScript的方法。

使用scrollIntoView

   这是一个实验中的功能, 如果你开发的项目需要兼容老旧的浏览器, 我不建议你用它。

   以下为MDN的描述

Element.scrollIntoView() 方法让当前的元素滚动到浏览器窗口的可视区域内。

   具体用法建议直接查看mdn文档, 此处贴一下用法

<div id="top-block"></div>
<div>
   <div class="block"></div>
   <div class="block"></div>
   <div class="block"></div>
   <div class="block"></div>
</div>

<script>

    function backToTop() {
        document.querySelector('#top-block').scrollIntoView({
           behavior: 'smooth',
           block: 'start'
       })
    }

</script>

使用scroll api(推荐)

   相比 scrollIntoView,scroll 使用上更加简洁,详情可参考文档

const toTop = () => {
  scroll({
    left: 0,
    top: 0,
    behavior: 'smooth',
  });
}

扩展:锚点定位的实现

  1. 使用上文的 scrollToPosition 函数, distance为需要定位的div的offsetTop, 前提是该div的offsetParent为body
  2. 直接使用 scrollIntoView

如果本文帮助了你, 请给我点个赞吧!!!