• 手把手教你写一个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,大概就是这样,有空再调整吧、、、

  • 相关阅读:
    【转】ios输入框被键盘挡住的解决办法
    【转】操作系统Unix、Windows、Mac OS、Linux的故事
    mac 下删除非空文件夹
    解决Win7 64bit + VS2013 使用opencv时出现提“应用程序无法正常启动(0xc000007b)”错误
    图的邻接表表示
    图的邻接矩阵表示
    并查集
    05-树9 Huffman Codes及基本操作
    05-树7 堆中的路径
    堆的操作集
  • 原文地址:https://www.cnblogs.com/niconi/p/7085457.html
Copyright © 2020-2023  润新知