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.
387 lines
9.9 KiB
387 lines
9.9 KiB
4 weeks ago
|
import Pager from './pager.vue';
|
||
|
import ElSelect from 'element-ui/packages/select';
|
||
|
import ElOption from 'element-ui/packages/option';
|
||
|
import ElInput from 'element-ui/packages/input';
|
||
|
import Locale from 'element-ui/src/mixins/locale';
|
||
|
import { valueEquals } from 'element-ui/src/utils/util';
|
||
|
|
||
|
export default {
|
||
|
name: 'ElPagination',
|
||
|
|
||
|
props: {
|
||
|
pageSize: {
|
||
|
type: Number,
|
||
|
default: 10
|
||
|
},
|
||
|
|
||
|
small: Boolean,
|
||
|
|
||
|
total: Number,
|
||
|
|
||
|
pageCount: Number,
|
||
|
|
||
|
pagerCount: {
|
||
|
type: Number,
|
||
|
validator(value) {
|
||
|
return (value | 0) === value && value > 4 && value < 22 && (value % 2) === 1;
|
||
|
},
|
||
|
default: 7
|
||
|
},
|
||
|
|
||
|
currentPage: {
|
||
|
type: Number,
|
||
|
default: 1
|
||
|
},
|
||
|
|
||
|
layout: {
|
||
|
default: 'prev, pager, next, jumper, ->, total'
|
||
|
},
|
||
|
|
||
|
pageSizes: {
|
||
|
type: Array,
|
||
|
default() {
|
||
|
return [10, 20, 30, 40, 50, 100];
|
||
|
}
|
||
|
},
|
||
|
|
||
|
popperClass: String,
|
||
|
|
||
|
prevText: String,
|
||
|
|
||
|
nextText: String,
|
||
|
|
||
|
background: Boolean,
|
||
|
|
||
|
disabled: Boolean,
|
||
|
|
||
|
hideOnSinglePage: Boolean
|
||
|
},
|
||
|
|
||
|
data() {
|
||
|
return {
|
||
|
internalCurrentPage: 1,
|
||
|
internalPageSize: 0,
|
||
|
lastEmittedPage: -1,
|
||
|
userChangePageSize: false
|
||
|
};
|
||
|
},
|
||
|
|
||
|
render(h) {
|
||
|
const layout = this.layout;
|
||
|
if (!layout) return null;
|
||
|
if (this.hideOnSinglePage && (!this.internalPageCount || this.internalPageCount === 1)) return null;
|
||
|
|
||
|
let template = <div class={['el-pagination', {
|
||
|
'is-background': this.background,
|
||
|
'el-pagination--small': this.small
|
||
|
}] }></div>;
|
||
|
const TEMPLATE_MAP = {
|
||
|
prev: <prev></prev>,
|
||
|
jumper: <jumper></jumper>,
|
||
|
pager: <pager currentPage={ this.internalCurrentPage } pageCount={ this.internalPageCount } pagerCount={ this.pagerCount } on-change={ this.handleCurrentChange } disabled={ this.disabled }></pager>,
|
||
|
next: <next></next>,
|
||
|
sizes: <sizes pageSizes={ this.pageSizes }></sizes>,
|
||
|
slot: <slot>{ this.$slots.default ? this.$slots.default : '' }</slot>,
|
||
|
total: <total></total>
|
||
|
};
|
||
|
const components = layout.split(',').map((item) => item.trim());
|
||
|
const rightWrapper = <div class="el-pagination__rightwrapper"></div>;
|
||
|
let haveRightWrapper = false;
|
||
|
|
||
|
template.children = template.children || [];
|
||
|
rightWrapper.children = rightWrapper.children || [];
|
||
|
components.forEach(compo => {
|
||
|
if (compo === '->') {
|
||
|
haveRightWrapper = true;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (!haveRightWrapper) {
|
||
|
template.children.push(TEMPLATE_MAP[compo]);
|
||
|
} else {
|
||
|
rightWrapper.children.push(TEMPLATE_MAP[compo]);
|
||
|
}
|
||
|
});
|
||
|
|
||
|
if (haveRightWrapper) {
|
||
|
template.children.unshift(rightWrapper);
|
||
|
}
|
||
|
|
||
|
return template;
|
||
|
},
|
||
|
|
||
|
components: {
|
||
|
Prev: {
|
||
|
render(h) {
|
||
|
return (
|
||
|
<button
|
||
|
type="button"
|
||
|
class="btn-prev"
|
||
|
disabled={ this.$parent.disabled || this.$parent.internalCurrentPage <= 1 }
|
||
|
on-click={ this.$parent.prev }>
|
||
|
{
|
||
|
this.$parent.prevText
|
||
|
? <span>{ this.$parent.prevText }</span>
|
||
|
: <i class="el-icon el-icon-arrow-left"></i>
|
||
|
}
|
||
|
</button>
|
||
|
);
|
||
|
}
|
||
|
},
|
||
|
|
||
|
Next: {
|
||
|
render(h) {
|
||
|
return (
|
||
|
<button
|
||
|
type="button"
|
||
|
class="btn-next"
|
||
|
disabled={ this.$parent.disabled || this.$parent.internalCurrentPage === this.$parent.internalPageCount || this.$parent.internalPageCount === 0 }
|
||
|
on-click={ this.$parent.next }>
|
||
|
{
|
||
|
this.$parent.nextText
|
||
|
? <span>{ this.$parent.nextText }</span>
|
||
|
: <i class="el-icon el-icon-arrow-right"></i>
|
||
|
}
|
||
|
</button>
|
||
|
);
|
||
|
}
|
||
|
},
|
||
|
|
||
|
Sizes: {
|
||
|
mixins: [Locale],
|
||
|
|
||
|
props: {
|
||
|
pageSizes: Array
|
||
|
},
|
||
|
|
||
|
watch: {
|
||
|
pageSizes: {
|
||
|
immediate: true,
|
||
|
handler(newVal, oldVal) {
|
||
|
if (valueEquals(newVal, oldVal)) return;
|
||
|
if (Array.isArray(newVal)) {
|
||
|
this.$parent.internalPageSize = newVal.indexOf(this.$parent.pageSize) > -1
|
||
|
? this.$parent.pageSize
|
||
|
: this.pageSizes[0];
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
|
||
|
render(h) {
|
||
|
return (
|
||
|
<span class="el-pagination__sizes">
|
||
|
<el-select
|
||
|
value={ this.$parent.internalPageSize }
|
||
|
popperClass={ this.$parent.popperClass || '' }
|
||
|
size="mini"
|
||
|
on-input={ this.handleChange }
|
||
|
disabled={ this.$parent.disabled }>
|
||
|
{
|
||
|
this.pageSizes.map(item =>
|
||
|
<el-option
|
||
|
value={ item }
|
||
|
label={ item + this.t('el.pagination.pagesize') }>
|
||
|
</el-option>
|
||
|
)
|
||
|
}
|
||
|
</el-select>
|
||
|
</span>
|
||
|
);
|
||
|
},
|
||
|
|
||
|
components: {
|
||
|
ElSelect,
|
||
|
ElOption
|
||
|
},
|
||
|
|
||
|
methods: {
|
||
|
handleChange(val) {
|
||
|
if (val !== this.$parent.internalPageSize) {
|
||
|
this.$parent.internalPageSize = val = parseInt(val, 10);
|
||
|
this.$parent.userChangePageSize = true;
|
||
|
this.$parent.$emit('update:pageSize', val);
|
||
|
this.$parent.$emit('size-change', val);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
|
||
|
Jumper: {
|
||
|
mixins: [Locale],
|
||
|
|
||
|
components: { ElInput },
|
||
|
|
||
|
data() {
|
||
|
return {
|
||
|
userInput: null
|
||
|
};
|
||
|
},
|
||
|
|
||
|
watch: {
|
||
|
'$parent.internalCurrentPage'() {
|
||
|
this.userInput = null;
|
||
|
}
|
||
|
},
|
||
|
|
||
|
methods: {
|
||
|
handleKeyup({ keyCode, target }) {
|
||
|
// Chrome, Safari, Firefox triggers change event on Enter
|
||
|
// Hack for IE: https://github.com/ElemeFE/element/issues/11710
|
||
|
// Drop this method when we no longer supports IE
|
||
|
if (keyCode === 13) {
|
||
|
this.handleChange(target.value);
|
||
|
}
|
||
|
},
|
||
|
handleInput(value) {
|
||
|
this.userInput = value;
|
||
|
},
|
||
|
handleChange(value) {
|
||
|
this.$parent.internalCurrentPage = this.$parent.getValidCurrentPage(value);
|
||
|
this.$parent.emitChange();
|
||
|
this.userInput = null;
|
||
|
}
|
||
|
},
|
||
|
|
||
|
render(h) {
|
||
|
return (
|
||
|
<span class="el-pagination__jump">
|
||
|
{ this.t('el.pagination.goto') }
|
||
|
<el-input
|
||
|
class="el-pagination__editor is-in-pagination"
|
||
|
min={ 1 }
|
||
|
max={ this.$parent.internalPageCount }
|
||
|
value={ this.userInput !== null ? this.userInput : this.$parent.internalCurrentPage }
|
||
|
type="number"
|
||
|
disabled={ this.$parent.disabled }
|
||
|
nativeOnKeyup={ this.handleKeyup }
|
||
|
onInput={ this.handleInput }
|
||
|
onChange={ this.handleChange }/>
|
||
|
{ this.t('el.pagination.pageClassifier') }
|
||
|
</span>
|
||
|
);
|
||
|
}
|
||
|
},
|
||
|
|
||
|
Total: {
|
||
|
mixins: [Locale],
|
||
|
|
||
|
render(h) {
|
||
|
return (
|
||
|
typeof this.$parent.total === 'number'
|
||
|
? <span class="el-pagination__total">{ this.t('el.pagination.total', { total: this.$parent.total }) }</span>
|
||
|
: ''
|
||
|
);
|
||
|
}
|
||
|
},
|
||
|
|
||
|
Pager
|
||
|
},
|
||
|
|
||
|
methods: {
|
||
|
handleCurrentChange(val) {
|
||
|
this.internalCurrentPage = this.getValidCurrentPage(val);
|
||
|
this.userChangePageSize = true;
|
||
|
this.emitChange();
|
||
|
},
|
||
|
|
||
|
prev() {
|
||
|
if (this.disabled) return;
|
||
|
const newVal = this.internalCurrentPage - 1;
|
||
|
this.internalCurrentPage = this.getValidCurrentPage(newVal);
|
||
|
this.$emit('prev-click', this.internalCurrentPage);
|
||
|
this.emitChange();
|
||
|
},
|
||
|
|
||
|
next() {
|
||
|
if (this.disabled) return;
|
||
|
const newVal = this.internalCurrentPage + 1;
|
||
|
this.internalCurrentPage = this.getValidCurrentPage(newVal);
|
||
|
this.$emit('next-click', this.internalCurrentPage);
|
||
|
this.emitChange();
|
||
|
},
|
||
|
|
||
|
getValidCurrentPage(value) {
|
||
|
value = parseInt(value, 10);
|
||
|
|
||
|
const havePageCount = typeof this.internalPageCount === 'number';
|
||
|
|
||
|
let resetValue;
|
||
|
if (!havePageCount) {
|
||
|
if (isNaN(value) || value < 1) resetValue = 1;
|
||
|
} else {
|
||
|
if (value < 1) {
|
||
|
resetValue = 1;
|
||
|
} else if (value > this.internalPageCount) {
|
||
|
resetValue = this.internalPageCount;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (resetValue === undefined && isNaN(value)) {
|
||
|
resetValue = 1;
|
||
|
} else if (resetValue === 0) {
|
||
|
resetValue = 1;
|
||
|
}
|
||
|
|
||
|
return resetValue === undefined ? value : resetValue;
|
||
|
},
|
||
|
|
||
|
emitChange() {
|
||
|
this.$nextTick(() => {
|
||
|
if (this.internalCurrentPage !== this.lastEmittedPage || this.userChangePageSize) {
|
||
|
this.$emit('current-change', this.internalCurrentPage);
|
||
|
this.lastEmittedPage = this.internalCurrentPage;
|
||
|
this.userChangePageSize = false;
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
},
|
||
|
|
||
|
computed: {
|
||
|
internalPageCount() {
|
||
|
if (typeof this.total === 'number') {
|
||
|
return Math.max(1, Math.ceil(this.total / this.internalPageSize));
|
||
|
} else if (typeof this.pageCount === 'number') {
|
||
|
return Math.max(1, this.pageCount);
|
||
|
}
|
||
|
return null;
|
||
|
}
|
||
|
},
|
||
|
|
||
|
watch: {
|
||
|
currentPage: {
|
||
|
immediate: true,
|
||
|
handler(val) {
|
||
|
this.internalCurrentPage = this.getValidCurrentPage(val);
|
||
|
}
|
||
|
},
|
||
|
|
||
|
pageSize: {
|
||
|
immediate: true,
|
||
|
handler(val) {
|
||
|
this.internalPageSize = isNaN(val) ? 10 : val;
|
||
|
}
|
||
|
},
|
||
|
|
||
|
internalCurrentPage: {
|
||
|
immediate: true,
|
||
|
handler(newVal) {
|
||
|
this.$emit('update:currentPage', newVal);
|
||
|
this.lastEmittedPage = -1;
|
||
|
}
|
||
|
},
|
||
|
|
||
|
internalPageCount(newVal) {
|
||
|
/* istanbul ignore if */
|
||
|
const oldPage = this.internalCurrentPage;
|
||
|
if (newVal > 0 && oldPage === 0) {
|
||
|
this.internalCurrentPage = 1;
|
||
|
} else if (oldPage > newVal) {
|
||
|
this.internalCurrentPage = newVal === 0 ? 1 : newVal;
|
||
|
this.userChangePageSize && this.emitChange();
|
||
|
}
|
||
|
this.userChangePageSize = false;
|
||
|
}
|
||
|
}
|
||
|
};
|