magiccube-vue3
Version:
vue3-js版组件库
289 lines (273 loc) • 11.3 kB
JavaScript
import { ref, onMounted, computed, watchEffect } from 'vue'
const Pagination = {
name: 'McPagination',
props: {
total: {
type: [Number, String],
default: 0
},
pageSize: {
type: [Number, String],
default: 20
},
simple: {
type: Boolean,
default: false
},
startRow: {
type: [Number, String],
default: 0
},
changePageSize: {
type: Boolean,
default: true
},
showTotal: {
type: Boolean,
default: true
},
maxPageSize: {
type: Number,
default: 100
},
align: {
type: String,
default: 'center'
}
},
emits: ['change', 'error'],
setup(props, { emit }) {
const current = ref(1)
const jump = ref('')
const pageSizeEl = ref(null)
const gotoEl = ref(null)
const handlePage = (number) => {
if (props.startRow === number) return false
const params = {
pageSize: props.pageSize,
startRow: (number - 1) * props.pageSize
}
emit('change', params)
}
const handleClick = (type, number) => {
switch (type) {
case 'page': {
if (current.value === number) return false
const params = {
pageSize: props.pageSize,
startRow: (number - 1) * props.pageSize
}
emit('change', params)
break
}
case 'prev': {
if (current.value <= 1) return false
const params = {
pageSize: props.pageSize,
startRow: (current.value - 2) * props.pageSize
}
emit('change', params)
break
}
case 'next': {
const len = pageList.value.length
if (current.value >= pageList.value[len - 1]) return false
const params = {
pageSize: props.pageSize,
startRow: current.value * props.pageSize
}
emit('change', params)
break
}
case 'amount': {
const params = {
pageSize: props.pageSize,
startRow: (pageAmount.value - 1) * props.pageSize
}
emit('change', params)
break
}
case 'first': {
const params = {
pageSize: props.pageSize,
startRow: 0
}
emit('change', params)
break
}
}
current.value = number
}
const invalidNumber = n => !Number(n) || parseInt(n) !== Number(n) || Number(n) < 0
const handleChangePageSize = (e) => {
if (e.keyCode !== 13) return
let val = e.target.value
// 不能输入小数、负数、和非数字内容
if (invalidNumber(val)) {
e.target.value= props.pageSize
emit('error', new Error('请输入正确的数值'))
return
}
if(Number(val) > props.maxPageSize){
emit('error', new Error(`每页最多${props.maxPageSize}条数据`))
val = props.maxPageSize
e.target.value = props.maxPageSize
}
const params = {
pageSize: Number(val),
startRow: 0
}
if (pageSizeEl.value) pageSizeEl.value.blur()
emit('change', params)
}
const handleJump = (e) => {
if (e.keyCode !== 13) return
// 不能输入小数、负数、和非数字内容
if (invalidNumber(jump.value)) {
jump.value = ''
emit('error', new Error('请输入正确的数值'))
return
}
let _jump = Number(jump.value) || 1
const pageTotalCount = Math.ceil(props.total / props.pageSize)
if (_jump > pageTotalCount) _jump = pageTotalCount
const params = {
pageSize: props.pageSize,
startRow: (_jump - 1) * props.pageSize
}
current.value = _jump
jump.value = ''
gotoEl.value.blur()
emit('change', params)
}
const showNumber = (num) => {
if (current.value < 3) {
return num <= 5
} else if (current.value > pageAmount.value - 3) {
return num >= pageAmount.value - 4
} else {
return (num < current.value + 3 && num > current.value - 3) || num === current.value
}
}
const showEllipsis = (type) => {
if (type === 'front') {
return current.value - 3 >= 1
} else {
return pageList.value.length < pageAmount.value && pageAmount.value - current.value >= 3
}
}
const pageList = computed(() => {
const p = Math.ceil(props.total / props.pageSize)
const list = []
for (let i = 1; i <= p; i++) list.push(i)
return list.filter(page => showNumber(page))
})
const pageAmount = computed(() => {
return Math.ceil(props.total / props.pageSize) || 0
})
watchEffect(() => {
current.value = props.startRow / props.pageSize + 1
})
return () => {
if (props.total) {
return (
(
<div class={[
'mc-pagination',
`mc-pagination__align--${props.align}`
]}>
{
props.showTotal ? (
<div class="mc-pagination__total">
<span>共</span>
<em class="mc-pagination__amount">{props.total}</em>
<span>条</span>
</div>
) : ''
}
{
!props.simple && props.changePageSize ? (
<div class="mc-pagination__size">
<span>每页</span>
<span class="mc-pagination__input">
<input class="mc-pagination__input--inner"
ref={pageSizeEl}
value={props.pageSize}
autocomplete="off"
onKeypress={handleChangePageSize} />
</span>
<span>条</span>
</div>
) : ''
}
<div class="mc-pagination__pages">
<div class={[
'page-prev',
{ disabled: current.value === 1 }
]}
onClick={() => handleClick('prev', current.value - 1)}></div>
{
showEllipsis('front') ? (
<div class="ellipsis">
<i class="page-tip"
onClick={() => handleClick('first', 1)}>1</i> ...
</div>
) : ''
}
<div style="display:flex;align-items:center;">
{
pageList.value.map((page, idx) => (
<span class={[
'page-number',
{ 'simple': props.simple },
{ 'active': page === current.value }
]}
key={idx}
onClick={() => handleClick('page', page)}>
{page}
</span>
))
}
</div>
{
showEllipsis('behind') ? (
<div class="ellipsis">
... <i class="page-tip" onClick={() => handleClick('amount', pageAmount.value)}>{pageAmount.value}</i>
</div>
) : ''
}
<div class={[
'page-next',
{ disabled: pageAmount.value - current.value <= 0 }
]}
onClick={() => handleClick('next', current.value + 1)}></div>
</div>
{
!props.simple ? (
<div class="mc-pagination__goto">
<span>前往</span>
<span class="mc-pagination__input">
<input class="mc-pagination__input--inner"
ref={gotoEl}
v-model={jump.value}
autocomplete="off"
onKeypress={handleJump} />
</span>
<span>页</span>
</div>
) : ''
}
</div>
)
)
} else {
return ''
}
}
}
}
Pagination.install = (app) => {
app.component(Pagination.name, Pagination)
}
const McPagination = Pagination
export { McPagination, McPagination as default }