在React中写一个回到顶部组件(back to top)

前文说过,最近在写一个基于 React + WP-Rest 的独立主题,而本文所说的回到顶部组件即是它的一部分。

原理及演示

关于Element.scrollTop,MDN 上有很好的解释:

Element.scrollTop 属性可以获取或设置一个元素的内容垂直滚动的像素数。
一个元素的 scrollTop 值是这个元素的内容顶部到它的视口可见内容顶部的距离的度量。当一个元素的内容没有产生垂直方向的滚动条,那么它的 scrollTop 值为0。

当内容滚动时,Element.scrollTop的值会发生改变。根据scrollTop的变化设置组件状态,React 会自动更新 DOM,从而实现按钮的显示与隐藏。

演示地址:http://www.acgame.fun

组件

1.代码

import React from 'react'
import styled from 'styled-components'

class ScrollToTopWrapper extends React.Component {

    constructor(props){
        super(props);
        this.state = { hasScrolled: false }
        this.onScroll = this.onScroll.bind(this);
    }

  componentDidMount() {
    window.onscroll = this.onScroll;
  }

  onScroll = () => {
    if (document.documentElement.scrollTop > 100 && !this.state.hasScrolled) {
      this.setState({ hasScrolled: true })
    } else if (document.documentElement.scrollTop < 100 && this.state.hasScrolled) {
      this.setState({ hasScrolled: false })
    }
  }

  scrollToTop = () => {
    document.documentElement.scrollTop = 0
  }

  render() {
    return (
      <React.Fragment>
        {this.state.hasScrolled && (
          <ScrollToTopIconContainer onClick={this.scrollToTop}>
            <div>^</div>
            <Button>回到顶部</Button>
          </ScrollToTopIconContainer>
        )}
        <ScrollingWrapperContainer>
          {this.props.children}
        </ScrollingWrapperContainer>
      </React.Fragment>
    )
  }
}

export default ScrollToTopWrapper

const ScrollingWrapperContainer = styled.div`
`

const ScrollToTopIconContainer = styled.div`
  position: fixed;
  bottom: 20px;
  left: calc(50% - 50px);
  z-index: 2;
  cursor: pointer;
  opacity: 0.4;
  text-align: center;
  &:hover {
    opacity: 1;
    animation: wiggle 1s ease;
    animation-iteration-count: 1;
  }
  @keyframes wiggle {
    20% { transform: translateY(6px); }
    40% { transform: translateY(-6px); }
    60% { transform: translateY(4px); }
    80% { transform: translateY(-2px); }
    100% { transform: translateY(0); }
  }
`

const Button = styled.div`
  background: black;
  color: white;
  font-family: Teko;
  font-size: 16px;
  line-height: 32px;
  border-radius: 15px;
  width: 100px;
  padding: 4px 2px 4px 2px;
`

2.解释

当往下滑动的距离超过 100 像素时,设置布尔状态 hasScrolled 为 True,点击按钮后,回到顶部。

使用

我的工程基于 React-router,嵌套本组件后结构如下:

<HashRouter history={hashHistory}>
    <div className={classes.root}>
        <AppBar position="sticky">
            {……}
        </AppBar>
        <ScrollToTopWrapper>
            <Switch>
                <Route exact path="/" component={……}></Route>
                {……}
            </Switch>
        </ScrollToTopWrapper>
    </div>
</HashRouter>

具体使用效果见演示站:http://www.acgame.fun

梓喵出没博客(azimiao.com)版权所有,转载请注明链接:https://www.azimiao.com/6798.html
欢迎加入梓喵出没博客交流群:313732000

我来吐槽

*

*