ListArea滚动组件的实现

先上代码:

import React from 'react';

export default class ListArea extends React.Component {
  state = {
    currentIndex: 0,
    interval: 3000,
    suspend: false
  };

  componentDidMount() {
    this.props.list.length > 1 && this.initAnimation();
  }

  componentDidUpdate(prevProps, prevState) {
    this.props.list.length > 1 && !this.timer && this.initAnimation();
  }

  componentWillUnmount() {
    this.timer && clearInterval(this.timer);
  }

  mouseEnter() {
    this.props.isSuspend && this.setState({suspend: true});
  }

  mouseLeave() {
    this.props.isSuspend && this.setState({suspend: false});
  }

  initAnimation() {
    this.timer = setInterval(() => {
      const firstElem = this.firstElem;
      if (!this.state.suspend && firstElem) {
        if (this.props.isCarousel) {
          firstElem.style.marginLeft = `${-firstElem.offsetWidth}px`;
        }else firstElem.style.marginTop = `${-firstElem.offsetHeight}px`;

        // 等待css动画执行完毕后刷新数据
        setTimeout(() => {
          const {list, getList} = this.props;
          let {currentIndex} = this.state;

          if (getList) {
            // 数据小于临界值时自动请求下一页数据
            // 若最后一页数据为0或者接口异常未返回数据时,数组长度不会发生变化
            // 所以每隔n秒触发动画并查询数据长度时若数据长度持续位于临界值之下时就应该持续请求后台数据
            if (list.length - currentIndex <= 5) getList();
            if (list.length - currentIndex === 1) clearInterval(this.timer);

            this.setState({currentIndex: currentIndex + 1});

          }else this.setState({currentIndex: list.length - currentIndex === 1 ? 0 : currentIndex + 1});

        }, 600);
      }
    }, this.state.interval);
  }

  render() {
    const {className, list, contentCount = 1, item, getList} = this.props;
    const {currentIndex} = this.state;
    const _list = getList ? list : [...list, ...list];
    return (
      <div className={className}
           onMouseEnter={this.mouseEnter.bind(this)}
           onMouseLeave={this.mouseLeave.bind(this)}
      >
        {
          _list.map((l, i) => i >= currentIndex && i < contentCount + currentIndex + 1 && item(l, i, ref => {if (i === currentIndex) this.firstElem = ref}, currentIndex))
        }
      </div>
    )
  }
}

分析:

默认interval没3秒滚动一帧,suspend:false滚动,当前索引currentIndex:0,

componentDidMount中 传入的list条数>1时进行初始化动画initAnimation()(此处可以优化下:传入contentCount,n条时进行初始化轮播)

mouseEnter()鼠标移入后suspend=true,不滚动,mouseLeave()鼠标移出后suspend=false滚动。

滚动的动画效果,使用transition。

.transition {
  -webkit-transition: all .5s ease;
  -o-transition: all .5s ease;
  -moz-transition: all .5s ease;
  transition: all .5s ease;
}

在行中引入

isCarousel为传入的滚动方向,有传则方向为从右向左轮播,没传则方向从下往上轮播。

滚动使用css3效果,滚动到下一帧后更新展示数据。

 

欢迎一起交流!
【http://wuhairui.cnblogs.com/】

原文地址:https://www.cnblogs.com/wuhairui/p/13679075.html