React Hooks里面利用ahooks实现回到顶部功能

1,431 阅读2分钟

很多小伙伴写过在原生js里面回到顶部的功能,真正在上手react项目后,如何实现这一功能。最近在做项目的过程中就有这个需求,由于项目的技术栈是基于Antd-mobile+ahooks,里面并没有回到顶部功能的组件(我们知道antd是有的,所以am啥时候能跟进一点),话不多说,下面就简单实现一个回到顶部功能。

组件封装

因为回到顶部在许多页面都要使用,所以我们最好把它抽离成一个小组件得以复用,我们简单封装一下,代码如下:

import styles from './style.module.scss'
import backToTop from '../imgs/backToTop.svg'
interface Props {
  visible: boolean
  back: () => void
}

export default function BackToTop(props: Props) {
  return (
    <div
      className={styles.backToTop}
      onClick={() => {
        props.back()
      }}
      style={
        props.visible ? { visibility: 'visible' } : { visibility: 'hidden' }
      }>
      <div className={styles.back}>
      <img src={backToTop} alt="" />
      <span>返回顶部</span>
      </div>
    </div>
  )
}

样式简单写:

.backToTop {
  transition: all ease-in-out .05s;
  height: 20px;
  position: fixed;
  bottom: 100px;
  scroll-behavior: smooth;
  right: 20px;
}

.back {
  font-size: 12px;
  color: #007AFA;
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  align-items: center;
}

组件接收两个参数,visible控制组件显示隐藏,back是传入的滚动到顶部的回调函数。 接下来就在页面中实际使用一下这个组件,很多人可能首先想到的是监听scroll事件,判断scrollTop的距离来进行控制组件的显示隐藏,这次我们借助于ahooks这个开源库来实现,体验效果会更佳。ahooks 是由蚂蚁 umi 团队开源的React Hooks 工具库。ahooks 是基于 React Hooks进行封装的,提供了非常好用的一系列hooks,极大地降低了开发难度,提升了开发效率。

代码实现

我们首先导入react相关hooks和刚封装的组件

import React, { useEffect, useRef, useState } from 'react'
import BackToTop from '../components/BackToTop'
import styles from '../styles/Demo.module.scss'
import { useScroll } from 'ahooks'
export default function Demo() {
  // 控制回到顶部组件显示的状态
  const [backVisible, setBackVisible] = useState(false)
  // ref绑定在我们要监听的滚动区域Dom元素上
  const backRef = useRef<HTMLDivElement>(null)
  // 
  const scroll = useScroll(backRef)
  useEffect(() => {
    if (scroll.top > 400) {
      setBackVisible(true)
    } else {
      setBackVisible(false)
    }
  }, [scroll.top])
  return (
    <div className={styles.list} ref={backRef}>
      <ul>
       <li>1</li>
       <li>2</li>
       <li>3</li>
       <li>4</li>
       <li>5</li>
       <li>6</li>
       <li>7</li>
       <li>8</li>
       <li>9</li>
       <li>10</li>
     </ul>
     <BackToTop
        visible={backVisible}
        back={() => {
          backRef.current?.scrollTo({ behavior: 'smooth', top: 0, left: 0 })
        }}
      />
    </div>
  )

节流

这样一个基本的回到顶部功能就实现了,但是上述代码有一个不合理的地方,只要稍微滚动一下页面,就会触发页面的滚动事件的频繁触发,这就引发性能问题,因此,我们来实现一个节流函数:

export default function throttle(func: Function, delay: number) {
  let timer: NodeJS.Timeout | null
  return function () {
    if (!timer) {
      timer = setTimeout(function (this: typeof func) {
        timer = null
        func.apply(this, arguments)
      }, delay)
    }
  }
}

最后代码长这样:

useEffect(() => {
    const func = throttle(() => {
      if (scroll.top > 1000) {
        setBackVisible(true)
      } else {
        setBackVisible(false)
      }
    }, 500)
    func()
  }, [scroll.top])