分頁是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,大概就是這樣,有空再調整吧、、、