实现返回顶部效果:
- 滚动一定高度后从下到上平移出现
- 点击后自动滚动到顶部
- 滚动到顶部以后从上到下平移消失
实现逻辑
- 监听滚动,发现滚动距离大于阈值(目前设为视窗高度),则显示按钮,否则隐藏
- 判断条件:
document.documentElement.scrollTop>document.documentElement.clientHeight
- useState:用一个布尔值isVisible来表示当前元素显示或隐藏
- 控制按钮显示,监听isVisible,有两种方法
- 没有动画效果:返回的虚拟DOM里内联地写
style={{display: isVisible? "block":"none"}}
- 有平移效果:
ref.current.style.bottom=`${bottomBias+20}px`
搭配 transition: bottom 1s;
- 点击按钮,回到顶部
document.body.scrollTop = document.documentElement.scrollTop = 0;
代码
api
- bottomBias:距离底部的额外距离,适用于底部有导航栏的页面(导航栏高度是50),没有导航栏可以不传
1
| <BackToTop bottomBias={50}></BackToTop>
|
实现
js
index.jsx
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
| import React, { useEffect, useRef, useState } from "react"; import {jsThrottle} from "../../utils/throttle"; import './style.less'
const BackToTop=({bottomBias=0})=>{ const [isVisible, setIsVisible]=useState(false) const ref=useRef() function onClickHandle(){ document.body.scrollTop = document.documentElement.scrollTop = 0; } useEffect(()=>{ let timer=null const scrollHandle=()=>{ if(document.documentElement.scrollTop>document.documentElement.clientHeight){ setIsVisible(true) } else { setIsVisible(false) } } window.addEventListener("scroll", jsThrottle(scrollHandle, 1000))
return ()=>{ console.log("clear"); window.removeEventListener("scroll", scrollHandle) } },[])
useEffect(()=>{ if (isVisible){ console.log("show") ref.current.style.bottom=`${bottomBias+20}px` } else { console.log("hide") ref.current.style.bottom=`-40px` } },[isVisible])
return ( <div ref={ref} onClick={onClickHandle} className="back2top-container"> <i className="iconfont icon-arrowup"></i> </div> ) }
export default BackToTop
|
throttle
带强制执行的节流
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| export function jsThrottle(fn, delay=300){ let timer=null function fnThrottle(...args) { if (!timer){ timer=setTimeout(()=>{ fn(...args) timer=null },delay) } } return fnThrottle }
|
css
style.less
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| .back2top-container{ position: fixed; right: 20px; bottom: -40px; height: 40px; width: 40px; border-radius: 50%; border: 1px solid #ccc; text-align: center; line-height: 40px; background-color: rgba(255, 255, 255, 0.9); transition: bottom 1s;
i{ color: blueviolet; font-size: 24px; } }
|
iconfont
需要额外下载一个上箭头的icon,不用icon直接用文字也行
这里使用 iconfont图标库