vuecssuiant-designantdreactantantd-vueenterprisefrontendui-designvue-antdvue-antd-uivue3vuecomponent
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
533 lines
16 KiB
533 lines
16 KiB
<script> |
|
import PropTypes from '../_util/vue-types' |
|
import BaseMixin from '../_util/BaseMixin' |
|
import { hasProp } from '../_util/props-util' |
|
import Pager from './Pager' |
|
import Options from './Options' |
|
import LOCALE from './locale/zh_CN' |
|
import KEYCODE from './KeyCode' |
|
|
|
function noop () { |
|
} |
|
|
|
// 是否是正整数 |
|
function isInteger (value) { |
|
return typeof value === 'number' && |
|
isFinite(value) && |
|
Math.floor(value) === value |
|
} |
|
|
|
function defaultItemRender (page, type, element) { |
|
return element |
|
} |
|
|
|
export default { |
|
name: 'Pagination', |
|
mixins: [BaseMixin], |
|
props: { |
|
prefixCls: PropTypes.string.def('rc-pagination'), |
|
selectPrefixCls: PropTypes.string.def('rc-select'), |
|
current: PropTypes.number, |
|
defaultCurrent: PropTypes.number.def(1), |
|
total: PropTypes.number.def(0), |
|
pageSize: PropTypes.number, |
|
defaultPageSize: PropTypes.number.def(10), |
|
change: PropTypes.func.def(noop), |
|
hideOnSinglePage: PropTypes.bool.def(false), |
|
showSizeChanger: PropTypes.bool.def(false), |
|
showLessItems: PropTypes.bool.def(false), |
|
// showSizeChange: PropTypes.func.def(noop), |
|
selectComponentClass: PropTypes.any, |
|
showQuickJumper: PropTypes.oneOfType([PropTypes.bool, PropTypes.object]).def(false), |
|
showTitle: PropTypes.bool.def(true), |
|
pageSizeOptions: PropTypes.arrayOf(PropTypes.string), |
|
buildOptionText: PropTypes.func, |
|
showTotal: PropTypes.func, |
|
simple: PropTypes.bool, |
|
locale: PropTypes.object.def(LOCALE), |
|
itemRender: PropTypes.func.def(defaultItemRender), |
|
}, |
|
model: { |
|
prop: 'current', |
|
event: 'change', |
|
}, |
|
data () { |
|
const hasOnChange = this.onChange !== noop |
|
const hasCurrent = hasProp(this, 'current') |
|
if (hasCurrent && !hasOnChange) { |
|
console.warn('Warning: You provided a `current` prop to a Pagination component without an `onChange` handler. This will render a read-only component.'); // eslint-disable-line |
|
} |
|
let current = this.defaultCurrent |
|
if (hasCurrent) { |
|
current = this.current |
|
} |
|
|
|
let pageSize = this.defaultPageSize |
|
if (hasProp(this, 'pageSize')) { |
|
pageSize = this.pageSize |
|
} |
|
|
|
return { |
|
stateCurrent: current, |
|
stateCurrentInputValue: current, |
|
statePageSize: pageSize, |
|
} |
|
}, |
|
watch: { |
|
current (val) { |
|
this.setState({ |
|
stateCurrent: val, |
|
stateCurrentInputValue: val, |
|
}) |
|
}, |
|
pageSize (val) { |
|
const newState = {} |
|
let current = this.stateCurrent |
|
const newCurrent = this.calculatePage(val) |
|
current = current > newCurrent ? newCurrent : current |
|
if (!hasProp(this, 'current')) { |
|
newState.stateCurrent = current |
|
newState.stateCurrentInputValue = current |
|
} |
|
newState.statePageSize = val |
|
this.setState(newState) |
|
}, |
|
}, |
|
methods: { |
|
isValid (page) { |
|
return isInteger(page) && page >= 1 && page !== this.stateCurrent |
|
}, |
|
calculatePage (p) { |
|
let pageSize = p |
|
if (typeof pageSize === 'undefined') { |
|
pageSize = this.statePageSize |
|
} |
|
return Math.floor((this.total - 1) / pageSize) + 1 |
|
}, |
|
handleGoTO (event) { |
|
if (event.keyCode === KEYCODE.ENTER || event.type === 'click') { |
|
this.handleChange(this.stateCurrentInputValue) |
|
} |
|
}, |
|
prev () { |
|
if (this.hasPrev()) { |
|
this.handleChange(this.stateCurrent - 1) |
|
} |
|
}, |
|
next () { |
|
if (this.hasNext()) { |
|
this.handleChange(this.stateCurrent + 1) |
|
} |
|
}, |
|
hasPrev () { |
|
return this.stateCurrent > 1 |
|
}, |
|
hasNext () { |
|
return this.stateCurrent < this.calculatePage() |
|
}, |
|
handleKeyDown (event) { |
|
if (event.keyCode === KEYCODE.ARROW_UP || event.keyCode === KEYCODE.ARROW_DOWN) { |
|
event.preventDefault() |
|
} |
|
}, |
|
handleKeyUp (event) { |
|
const inputValue = event.target.value |
|
const stateCurrentInputValue = this.stateCurrentInputValue |
|
let value |
|
|
|
if (inputValue === '') { |
|
value = inputValue |
|
} else if (isNaN(Number(inputValue))) { |
|
value = stateCurrentInputValue |
|
} else { |
|
value = Number(inputValue) |
|
} |
|
|
|
if (value !== stateCurrentInputValue) { |
|
this.setState({ |
|
stateCurrentInputValue: value, |
|
}) |
|
} |
|
|
|
if (event.keyCode === KEYCODE.ENTER) { |
|
this.handleChange(value) |
|
} else if (event.keyCode === KEYCODE.ARROW_UP) { |
|
this.handleChange(value - 1) |
|
} else if (event.keyCode === KEYCODE.ARROW_DOWN) { |
|
this.handleChange(value + 1) |
|
} |
|
}, |
|
changePageSize (size) { |
|
let current = this.stateCurrent |
|
const newCurrent = this.calculatePage(size) |
|
current = current > newCurrent ? newCurrent : current |
|
if (typeof size === 'number') { |
|
if (!hasProp(this, 'pageSize')) { |
|
this.setState({ |
|
statePageSize: size, |
|
}) |
|
} |
|
if (!hasProp(this, 'current')) { |
|
this.setState({ |
|
stateCurrent: current, |
|
stateCurrentInputValue: current, |
|
}) |
|
} |
|
} |
|
this.$emit('update:pageSize', size) |
|
this.$emit('showSizeChange', current, size) |
|
this.$emit('change', current, size) |
|
}, |
|
handleChange (p) { |
|
let page = p |
|
if (this.isValid(page)) { |
|
const allTotal = this.calculatePage() |
|
if (page > allTotal) { |
|
page = allTotal |
|
} |
|
if (!hasProp(this, 'current')) { |
|
this.setState({ |
|
stateCurrent: page, |
|
stateCurrentInputValue: page, |
|
}) |
|
} |
|
// this.$emit('input', page) |
|
this.$emit('change', page, this.statePageSize) |
|
return page |
|
} |
|
return this.stateCurrent |
|
}, |
|
runIfEnter (event, callback, ...restParams) { |
|
if (event.key === 'Enter' || event.charCode === 13) { |
|
callback(...restParams) |
|
} |
|
}, |
|
runIfEnterPrev (event) { |
|
this.runIfEnter(event, this.prev) |
|
}, |
|
runIfEnterNext (event) { |
|
this.runIfEnter(event, this.next) |
|
}, |
|
runIfEnterJumpPrev (event) { |
|
this.runIfEnter(event, this.jumpPrev) |
|
}, |
|
runIfEnterJumpNext (event) { |
|
this.runIfEnter(event, this.jumpNext) |
|
}, |
|
getJumpPrevPage () { |
|
return Math.max(1, this.stateCurrent - (this.showLessItems ? 3 : 5)) |
|
}, |
|
getJumpNextPage () { |
|
return Math.min(this.calculatePage(), this.stateCurrent + (this.showLessItems ? 3 : 5)) |
|
}, |
|
jumpPrev () { |
|
this.handleChange(this.getJumpPrevPage()) |
|
}, |
|
jumpNext () { |
|
this.handleChange(this.getJumpNextPage()) |
|
}, |
|
}, |
|
render () { |
|
// When hideOnSinglePage is true and there is only 1 page, hide the pager |
|
if (this.hideOnSinglePage === true && this.total <= this.statePageSize) { |
|
return null |
|
} |
|
|
|
const locale = this.locale |
|
|
|
const prefixCls = this.prefixCls |
|
const allPages = this.calculatePage() |
|
const pagerList = [] |
|
let jumpPrev = null |
|
let jumpNext = null |
|
let firstPager = null |
|
let lastPager = null |
|
let gotoButton = null |
|
const goButton = (this.showQuickJumper && this.showQuickJumper.goButton) |
|
const pageBufferSize = this.showLessItems ? 1 : 2 |
|
const { stateCurrent, statePageSize } = this |
|
const prevPage = stateCurrent - 1 > 0 ? stateCurrent - 1 : 0 |
|
const nextPage = stateCurrent + 1 < allPages ? stateCurrent + 1 : allPages |
|
|
|
if (this.simple) { |
|
if (goButton) { |
|
if (typeof goButton === 'boolean') { |
|
gotoButton = ( |
|
<button |
|
type='button' |
|
onClick={this.handleGoTO} |
|
onKeyup={this.handleGoTO} |
|
> |
|
{locale.jump_to_confirm} |
|
</button> |
|
) |
|
} else { |
|
gotoButton = ( |
|
<span |
|
onClick={this.handleGoTO} |
|
onKeyup={this.handleGoTO} |
|
>{goButton}</span> |
|
) |
|
} |
|
gotoButton = ( |
|
<li |
|
title={this.showTitle ? `${locale.jump_to}${this.stateCurrent}/${allPages}` : null} |
|
class={`${prefixCls}-simple-pager`} |
|
> |
|
{gotoButton} |
|
</li> |
|
) |
|
} |
|
const hasPrev = this.hasPrev() |
|
const hasNext = this.hasNext() |
|
return ( |
|
<ul class={`${prefixCls} ${prefixCls}-simple`}> |
|
<li |
|
title={this.showTitle ? locale.prev_page : null} |
|
onClick={this.prev} |
|
tabIndex={hasPrev ? 0 : null} |
|
onKeypress={this.runIfEnterPrev} |
|
class={`${hasPrev ? '' : `${prefixCls}-disabled`} ${prefixCls}-prev`} |
|
aria-disabled={!this.hasPrev()} |
|
> |
|
{this.itemRender(prevPage, 'prev', <a class={`${prefixCls}-item-link`} />)} |
|
</li> |
|
<li |
|
title={this.showTitle ? `${stateCurrent}/${allPages}` : null} |
|
class={`${prefixCls}-simple-pager`} |
|
> |
|
<input |
|
type='text' |
|
value={this.stateCurrentInputValue} |
|
onKeydown={this.handleKeyDown} |
|
onKeyup={this.handleKeyUp} |
|
onInput={this.handleKeyUp} |
|
size='3' |
|
/> |
|
<span class={`${prefixCls}-slash`}>/</span> |
|
{allPages} |
|
</li> |
|
<li |
|
title={this.showTitle ? locale.next_page : null} |
|
onClick={this.next} |
|
tabIndex='0' |
|
onKeypress={this.runIfEnterNext} |
|
class={`${hasNext ? '' : `${prefixCls}-disabled`} ${prefixCls}-next`} |
|
aria-disabled={!this.hasNext()} |
|
> |
|
{this.itemRender(nextPage, 'next', <a class={`${prefixCls}-item-link`} />)} |
|
</li> |
|
{gotoButton} |
|
</ul> |
|
) |
|
} |
|
if (allPages <= 5 + pageBufferSize * 2) { |
|
for (let i = 1; i <= allPages; i++) { |
|
const active = stateCurrent === i |
|
pagerList.push( |
|
<Pager |
|
locale={locale} |
|
rootPrefixCls={prefixCls} |
|
onClick={this.handleChange} |
|
onKeypress={this.runIfEnter} |
|
key={i} |
|
page={i} |
|
active={active} |
|
showTitle={this.showTitle} |
|
itemRender={this.itemRender} |
|
/> |
|
) |
|
} |
|
} else { |
|
const prevItemTitle = this.showLessItems ? locale.prev_3 : locale.prev_5 |
|
const nextItemTitle = this.showLessItems ? locale.next_3 : locale.next_5 |
|
jumpPrev = ( |
|
<li |
|
title={this.showTitle ? prevItemTitle : null} |
|
key='prev' |
|
onClick={this.jumpPrev} |
|
tabIndex='0' |
|
onKeypress={this.runIfEnterJumpPrev} |
|
class={`${prefixCls}-jump-prev`} |
|
> |
|
{this.itemRender( |
|
this.getJumpPrevPage(), 'jump-prev', <a class={`${prefixCls}-item-link`} /> |
|
)} |
|
</li> |
|
) |
|
jumpNext = ( |
|
<li |
|
title={this.showTitle ? nextItemTitle : null} |
|
key='next' |
|
tabIndex='0' |
|
onClick={this.jumpNext} |
|
onKeypress={this.runIfEnterJumpNext} |
|
class={`${prefixCls}-jump-next`} |
|
> |
|
{this.itemRender( |
|
this.getJumpNextPage(), 'jump-next', <a class={`${prefixCls}-item-link`} /> |
|
)} |
|
</li> |
|
) |
|
lastPager = ( |
|
<Pager |
|
locale={locale} |
|
last |
|
rootPrefixCls={prefixCls} |
|
onClick={this.handleChange} |
|
onKeypress={this.runIfEnter} |
|
key={allPages} |
|
page={allPages} |
|
active={false} |
|
showTitle={this.showTitle} |
|
itemRender={this.itemRender} |
|
/> |
|
) |
|
firstPager = ( |
|
<Pager |
|
locale={locale} |
|
rootPrefixCls={prefixCls} |
|
onClick={this.handleChange} |
|
onKeypress={this.runIfEnter} |
|
key={1} |
|
page={1} |
|
active={false} |
|
showTitle={this.showTitle} |
|
itemRender={this.itemRender} |
|
/> |
|
) |
|
|
|
let left = Math.max(1, stateCurrent - pageBufferSize) |
|
let right = Math.min(stateCurrent + pageBufferSize, allPages) |
|
|
|
if (stateCurrent - 1 <= pageBufferSize) { |
|
right = 1 + pageBufferSize * 2 |
|
} |
|
|
|
if (allPages - stateCurrent <= pageBufferSize) { |
|
left = allPages - pageBufferSize * 2 |
|
} |
|
|
|
for (let i = left; i <= right; i++) { |
|
const active = stateCurrent === i |
|
pagerList.push( |
|
<Pager |
|
locale={locale} |
|
rootPrefixCls={prefixCls} |
|
onClick={this.handleChange} |
|
onKeypress={this.runIfEnter} |
|
key={i} |
|
page={i} |
|
active={active} |
|
showTitle={this.showTitle} |
|
itemRender={this.itemRender} |
|
/> |
|
) |
|
} |
|
|
|
if (stateCurrent - 1 >= pageBufferSize * 2 && stateCurrent !== 1 + 2) { |
|
pagerList[0] = ( |
|
<Pager |
|
locale={locale} |
|
rootPrefixCls={prefixCls} |
|
onClick={this.handleChange} |
|
onKeypress={this.runIfEnter} |
|
key={left} |
|
page={left} |
|
class={`${prefixCls}-item-after-jump-prev`} |
|
active={false} |
|
showTitle={this.showTitle} |
|
itemRender={this.itemRender} |
|
/> |
|
) |
|
pagerList.unshift(jumpPrev) |
|
} |
|
if (allPages - stateCurrent >= pageBufferSize * 2 && stateCurrent !== allPages - 2) { |
|
pagerList[pagerList.length - 1] = ( |
|
<Pager |
|
locale={locale} |
|
rootPrefixCls={prefixCls} |
|
onClick={this.handleChange} |
|
onKeypress={this.runIfEnter} |
|
key={right} |
|
page={right} |
|
class={`${prefixCls}-item-before-jump-next`} |
|
active={false} |
|
showTitle={this.showTitle} |
|
itemRender={this.itemRender} |
|
/> |
|
) |
|
pagerList.push(jumpNext) |
|
} |
|
|
|
if (left !== 1) { |
|
pagerList.unshift(firstPager) |
|
} |
|
if (right !== allPages) { |
|
pagerList.push(lastPager) |
|
} |
|
} |
|
|
|
let totalText = null |
|
|
|
if (this.showTotal) { |
|
totalText = ( |
|
<li class={`${prefixCls}-total-text`}> |
|
{this.showTotal( |
|
this.total, |
|
[ |
|
(stateCurrent - 1) * statePageSize + 1, |
|
stateCurrent * statePageSize > this.total ? this.total : stateCurrent * statePageSize, |
|
] |
|
)} |
|
</li> |
|
) |
|
} |
|
const prevDisabled = !this.hasPrev() |
|
const nextDisabled = !this.hasNext() |
|
const buildOptionText = this.buildOptionText || this.$scopedSlots.buildOptionText |
|
return ( |
|
<ul |
|
class={`${prefixCls}`} |
|
unselectable='unselectable' |
|
> |
|
{totalText} |
|
<li |
|
title={this.showTitle ? locale.prev_page : null} |
|
onClick={this.prev} |
|
tabIndex={prevDisabled ? null : 0} |
|
onKeypress={this.runIfEnterPrev} |
|
class={`${!prevDisabled ? '' : `${prefixCls}-disabled`} ${prefixCls}-prev`} |
|
aria-disabled={prevDisabled} |
|
> |
|
{this.itemRender(prevPage, 'prev', <a class={`${prefixCls}-item-link`} />)} |
|
</li> |
|
{pagerList} |
|
<li |
|
title={this.showTitle ? locale.next_page : null} |
|
onClick={this.next} |
|
tabIndex={nextDisabled ? null : 0} |
|
onKeypress={this.runIfEnterNext} |
|
class={`${!nextDisabled ? '' : `${prefixCls}-disabled`} ${prefixCls}-next`} |
|
aria-disabled={nextDisabled} |
|
> |
|
{this.itemRender(nextPage, 'next', <a class={`${prefixCls}-item-link`} />)} |
|
</li> |
|
<Options |
|
locale={locale} |
|
rootPrefixCls={prefixCls} |
|
selectComponentClass={this.selectComponentClass} |
|
selectPrefixCls={this.selectPrefixCls} |
|
changeSize={this.showSizeChanger ? this.changePageSize : null} |
|
current={stateCurrent} |
|
pageSize={statePageSize} |
|
pageSizeOptions={this.pageSizeOptions} |
|
buildOptionText={buildOptionText || null} |
|
quickGo={this.showQuickJumper ? this.handleChange : null} |
|
goButton={goButton} |
|
/> |
|
</ul> |
|
) |
|
}, |
|
} |
|
</script>
|
|
|