手把手教你写一个react分页组件

分页是web项目中hin常见的功能;今天就来做一个基于react框架的分页插件;

首先,思路是父级组件通过props传入数据总数,每页显示条数,显示多少按钮,当前页发生变化时的处理函数等配置;其次,组件本身维护一个数组,数组中记录当前应该显示的页数序列,用户触发跳页操作时更新这个数组并调用父组件传入的处理函数;

先看一下要完成的效果:

分页效果 

嘛~就是这么简单。下面开始。。

一、定义props类型和默认props

static propTypes = {
    pageSize: PropTypes.number, /* 每页显示多少行 */
    currentPage: PropTypes.number, /* 默认选中页 */
    dataCount: PropTypes.number,  /* 数据总条数 */
    maxSize: PropTypes.number,  /* 最多显示按钮数 */
    forbidJump: PropTypes.bool, /* 是否隐藏跳页操作相关按钮 */
    hidePreAndNext: PropTypes.bool, /* 是否隐藏上一页下一页按钮 */
    previousLabel: PropTypes.string,  /* 上一页按钮显示文字 */
    nextLabel: PropTypes.string,  /* 下一页显示文字 */
    onChange: PropTypes.func   /* 触发跳页操作时调用的处理函数 */
  }
  static defaultProps = {
    pageSize: 10,
    currentPage: 1,
    dataCount: 0,
    forbidJump: false,
    hidePreAndNext: false,
    maxSize: 5,
    previousLabel: '<',
    nextLabel: '>',
    onChange: null
  }

二、创建state,维护组件状态(_getBtnIndexList方法返回页数按钮序列数组,因为constructor和componentWillReceiveProps中都要用到,故封装成一个方法)

constructor(props) {
    super(props)
    let _indexList = this._getBtnIndexList()
    this.state = {
      currentPage: props.currentPage,
      btnIndexList: [],   /* 维护要显示的页码序列 */
      pagesCount: 0,    /* 总页数 */
      targetPage:null      /* 跳转操作临时存储输入值*/
    }
  }

 三、_getBtnIndexList方法实现

_getBtnIndexList = (newProps) => {
    let _props = newProps || this.props
    let _pagesCount = Math.ceil(_props.dataCount / _props.pageSize), _maxSize = _props.maxSize, _btnInsexlist = []
    if (_pagesCount <= _maxSize + 1) {
      for (let i = 1; i <= _pagesCount; i++) {
        _btnInsexlist.push(i)
      }
      return {
        btnInsexlist: _btnInsexlist,
        pagesCount: _pagesCount
      }
    }
    for (let i = 1; i <= _maxSize - 1; i++) {
      _btnInsexlist.push(i)
    }
    _btnInsexlist.push('...')
    _btnInsexlist.push(_pagesCount)
    return {
      btnInsexlist: _btnInsexlist,
      pagesCount: _pagesCount
    }
  }

四、将this.state.btnIndexList数组map到render方法中

let _btns = []
    for (let i = 0; i < this.state.btnIndexList.length; i++) {
      if (typeof this.state.btnIndexList[i] === 'number') {
        _btns.push(
          <li className={this.state.currentPage === this.state.btnIndexList[i] ? 'active' : ''} key={`page${i}`} onClick={() => { this._handleJumpPage(this.state.btnIndexList[i]) }}>
            <a href="javascript:;">{this.state.btnIndexList[i]}</a>
          </li>
        )
      } else {
        _btns.push(
          <li key={`page${i}`}>
            <span>{this.state.btnIndexList[i]}</span>
          </li>
        )
      }
    }

  。。。。。。此处省略132个字

<ul>
          {
            /**
             * 是否隐藏上页下页操作按钮
             */
            this.props.hidePreAndNext ? null : (
              <li
                className={this.state.currentPage === 1 ? 'disabled' : ''}
                onClick={() => {
                  this._goPrePage()
                }}
              >
                <a href="javascript:;">{this.props.previousLabel || '<'}</a>
              </li>
            )
          }

          {_btns}
          {
            /**
             * 是否隐藏上页下页操作按钮
             */
            this.props.hidePreAndNext ? null : (
              <li
                className={this.state.currentPage === this.state.pagesCount ? 'disabled' : ''}
                onClick={() => {
                  this._goNextPage()
                }}
              >
                <a href="javascript:;">{this.props.nextLabel || '>'}</a>
              </li>
            )
          }

          {
            /**
             * 是否隐藏跳页操作按钮
             */
            this.props.forbidJump ? null : (
              <li className="dis">
                共{this.state.btnIndexList[this.state.btnIndexList.length - 1]}页,到第<input
                  type="tel"
                  value={this.state.targetPage}
                  onChange={(e) => {
                    this.setState({
                      targetPage: /^d+$/.test(e.target.value) ? e.target.value - 0 : ''
                    })
                  }}
                /><div style={{ lineHeight: '31px', paddingRight: '15px', display: 'inline' }}>页</div>
              </li>
            )
          }

          {
            this.props.forbidJump ? null : (
              <li className="dis">
                <a
                  href="javascript:;"
                  onClick={() => {
                    if (!/^d+$/.test(this.state.targetPage)) {
                      return
                    }
                    this.state.targetPage > this.state.pagesCount ? this._handleJumpPage(this.state.pagesCount) : this._handleJumpPage(this.state.targetPage)
                    this.setState({
                      targetPage: ''
                    })
                  }}
                >确定</a>
              </li>
            )
          }
        </ul>

 五、跳页分页处理(改变按钮序列号数组)

_handleJumpPage = (pageIndex) => {
    if (pageIndex === this.state.currentPage) {
      return
    }
    this.setState({ currentPage: pageIndex })
    if (this.state.pagesCount <= this.props.maxSize) {
      return
    }
    if (pageIndex < (this.props.maxSize - 1)) {
      let _indexList = this._getBtnIndexList()
      this.setState({
        btnIndexList: _indexList.btnInsexlist
      })
      return
    }
    if (pageIndex > this.state.pagesCount - (this.props.maxSize - 2)) {
      let _btns = [1, '...']
      for (let i = (this.state.pagesCount - (this.props.maxSize - 2)); i <= this.state.pagesCount; i++) {
        _btns.push(i)
      }
      this.setState({
        btnIndexList: _btns
      })
      return
    }
    if (pageIndex > (this.props.maxSize - 2)) {
      let _pre = Math.ceil((this.props.maxSize - 3) / 2)
      let _btns = [1, '...']
      for (let i = _pre; i > 0; i--) {
        _btns.push(pageIndex - i)
      }
      _btns.push(pageIndex)

      if ((this.state.pagesCount - pageIndex) <= (this.props.maxSize - 3)) {
        for (let i = pageIndex + 1; i <= this.state.pagesCount; i++) {
          _btns.push(i)
        }
      } else {
        for (let i = 1; i <= _pre; i++) {
          _btns.push(pageIndex + i)
        }
        _btns.push('...')
        _btns.push(this.state.pagesCount)
      }

      this.setState({
        btnIndexList: _btns
      })
    }
  }

ok,大概就是这样,有空再调整吧、、、

原文地址:https://www.cnblogs.com/niconi/p/7085457.html