【react 分页器】 基于react-virtualized组件的分页器

react-virtualized 组件本身没有提供分页器功能,见这个issue:https://github.com/bvaughn/react-virtualized/issues/24

如果想给react-virtualized实现的表格添加分页器功能,需要自己手动实现一个分页器,网上有一个参考代码:

https://codesandbox.io/s/mm3kvjo0z9

分页器代码:

Paginator.js

import React from 'react'
import { Button } from 'semantic-ui-react'


const BetweenButton = () => <Button content='...' default' }} />

const Paginator = ({ currentPage, onPageChange, range = 3, pageCount }) => {
  const renderedPages = [...Array(range * 2 + 1).keys()]
    .map(i => currentPage - range + i)
    .filter(i => i > 0 && i <= pageCount)

  const showStart = currentPage - range > 1
  const showEnd = currentPage + range < pageCount

  return (
    <Button.Group compact>
      {showStart && (
        [
          <Button content={1} onClick={() => onPageChange(1)} />,
          <BetweenButton />
        ]
      )}
      {renderedPages.map(page => (
        <Button 
          key={page}
          onClick={() => onPageChange(page)} 
          content={page}
          primary={currentPage === page}
        />
      ))}
      {showEnd && (
        [
          <BetweenButton />, 
          <Button content={pageCount} onClick={() => onPageChange(pageCount)} />
        ]
      )}
    </Button.Group>
  )
}

export default Paginator

使用该分页器:

index.js

import React, { Component } from 'react'
import { render } from 'react-dom'
import { Icon, Header, Button } from 'semantic-ui-react'
import { Column } from 'react-virtualized'
import styled from 'styled-components'

import VirtualizedTable from './VirtualizedTable'
import Paginator from './Paginator'
import { getRows } from './utils'


const count = 100000
const rows = getRows(count)

const Wrapper = styled.div`
  margin: 10px;
`

const CountCell = ({ cellData }) => (
  <div>
    <Icon name='mail' color='green' />{cellData}
  </div>
)

class App extends Component {
  constructor() {
    super()
    this.state = { 
      page: 1, 
      perPage: 18, 
      scrollToIndex: undefined 
    }
    this.handleRowsScroll = this.handleRowsScroll.bind(this)
    this.handlePageChange = this.handlePageChange.bind(this)
  }

  handleRowsScroll({ stopIndex }) {
    this.setState(prevState => {
      const page = Math.ceil(stopIndex / prevState.perPage)
      return { page, scrollToIndex: undefined }
    })
  }

  handlePageChange(page) {
    this.setState(prevState => {
      const scrollToIndex = (page - 1) * prevState.perPage
      return { page, scrollToIndex }
    })
  }

  render() {
    const { page, perPage, scrollToIndex } = this.state

    const headerHeight = 30
    const rowHeight = 40
    const height = rowHeight * perPage + headerHeight
    const rowCount = rows.length
    const pageCount = Math.ceil(rowCount / perPage)

    return (
      <Wrapper>
        <Header as='h1'>React virtualized table with pagination</Header>
        <p>
          <Paginator
            pageCount={pageCount}
            currentPage={page}
            onPageChange={this.handlePageChange}
          />
        </p>
        <VirtualizedTable
          rowHeight={rowHeight}
          headerHeight={headerHeight}
          height={height}
          rowCount={rowCount}
          rows={rows}
          onRowsRendered={this.handleRowsScroll}
          scrollToIndex={scrollToIndex}
          scrollToAlignment='start'
        >
          <Column label='Id' dataKey='id' width={100} /> 
          <Column label='Name' dataKey='name' width={250} /> 
          <Column label='Count' dataKey='count' width={100} cellRenderer={CountCell} />
        </VirtualizedTable>
      </Wrapper>
    )
  }
}

render(<App />, document.getElementById('root'));

这个分页器没有设置一页多少行的功能,也没有直接跳转到多少行的功能,我给它加了这两个功能:

在index.js中加入如下代码:

使用了两个input受控组件,关于受控组件:https://segmentfault.com/a/1190000012404114

          <Paginator pageCount={pageCount} currentPage={currentPage} onPageChange={this.handlePageChange} />

          <input type="number" min="1" max="100" value={this.state.perPage} onChange={(e) => {
            if(e.target.value>=1&&e.target.value<=100){
              this.setState({perPage: e.target.value, currentPage:1,});
            }else{
              alert('the rows on a page should between 1 and 100');
            }
          }} /> rows on a page; jump to page 
          <input type="number" min="1" value={this.state.currentPage} onChange={(e)=>{
            if(e.target.value>=1 && e.target.value<=pageCount){
              this.setState({currentPage:e.target.value});
            }else{
              alert('the page number should exist!')
            }
          }}/>