<template>
<div class="pagination">
<ul @click="currentChange($event)">
<!-- 上一页 -->
<li :class="['preButton', currentPage === 1 ? 'disabled' : '']"><</li>
<!-- 第一页 -->
<li
:class="[1 == currentPage ? 'active' : '', 'page']"
v-if="pageCount > 0"
>
1
</li>
<li v-if="showPrevMore">...</li>
<!-- 中间页 -->
<li
v-for="item in showPage"
:class="[item == currentPage ? 'active' : '', 'page']"
>
{{ item }}
</li>
<li v-if="showNextMore">...</li>
<!-- 最后一页 -->
<li
:class="[pageCount == currentPage ? 'active' : '', 'page']"
v-if="pageCount > 1"
>
{{ Number(pageCount) }}
</li>
<!-- 下一页 -->
<li :class="['nextButton', currentPage === pageCount ? 'disabled' : '']">
>
</li>
<!-- 总共 -->
<li class="total">
共<span>{{ total }}</span
>条
</li>
<select
name="limit"
id="limit"
class="pageSizes-li"
v-model="limit"
@change="limitChangeHnadler"
>
<option
v-for="item in pageSizes"
:value="item"
:label="item + '页/条'"
></option>
</select>
</ul>
</div>
</template>
<script>
import { propsType } from "./constant";
import { isChangeCurrentPage } from "./utils";
export default {
name: "YuPagination",
props: propsType,
data() {
return {
limit: this.pageSizes[0],
showPrevMore: false,
showNextMore: false,
};
},
computed: {
pageCount() {
return Math.ceil(this.total / this.pageSize);
},
showPage() {
const array = [],
pagerCount = this.pagerCount,
halfPagerCount = (pagerCount - 1) / 2,
currentPage = Number(this.currentPage),
pageCount = Number(this.pageCount);
let showPrevMore = false,
showNextMore = false;
if (pageCount > pagerCount) {
if (currentPage > pagerCount - halfPagerCount) {
console.log('显示左边',currentPage,'currentPage',currentPage > pagerCount - halfPagerCount,);
showPrevMore = true;
}
if (currentPage < pageCount - halfPagerCount) {
console.log('显示右边',currentPage,'currentPage',currentPage < pageCount - halfPagerCount);
showNextMore = true;
}
}
if (showPrevMore && !showNextMore) {
const startPage = pageCount - (pagerCount - 2);
for (let i = startPage; i < pageCount; i++) {
array.push(i);
}
} else if (!showPrevMore && showNextMore) {
for (let i = 2; i < pagerCount; i++) {
array.push(i);
}
} else if (showPrevMore && showNextMore) {
const offset = Math.floor(pagerCount / 2) - 1;
for (let i = currentPage - offset; i <= currentPage + offset; i++) {
array.push(i);
}
} else {
for (let i = 2; i < pageCount; i++) {
array.push(i);
}
}
this.showPrevMore = showPrevMore;
this.showNextMore = showNextMore;
return array;
},
},
methods: {
limitChangeHnadler() {
this.$emit("update:pageSize", this.limit);
this.$emit("pageSizeChange");
},
currentChange(e) {
if (isChangeCurrentPage(e, this.disabled))
this.clickPageHandler(e.target.textContent);
if (e.target.className == "preButton") this.preClickHandler();
else if (e.target.className == "nextButton") this.nextClickHandler();
},
clickPageHandler(value) {
this.$emit("update:currentPage", parseInt(value));
this.$emit("currentChange");
},
preClickHandler() {
if (this.currentPage > 1) {
this.$emit("update:currentPage", this.currentPage - 1);
this.preClick();
}
},
nextClickHandler() {
if (this.currentPage < this.pageCount) {
this.$emit("update:currentPage", this.currentPage + 1);
this.nextClick();
}
},
},
};
</script>
<style type="text/css" scoped>
.pagination {
display: flex;
justify-content: flex-end;
align-items: center;
width: 100%;
}
ul {
display: flex;
justify-content: space-around;
margin: 0 100px;
}
li {
display: flex;
align-items: center;
justify-content: center;
width: 40px;
height: 40px;
line-height: 40px;
list-style: none;
margin: 0 5px;
border: 1px solid #eee;
}
ul li:last-child {
width: auto;
height: auto;
border: none;
}
ul li:last-child span {
margin: 0 5px;
}
.active {
color: orange;
background-color: #333;
}
li:hover {
cursor: pointer;
}
.total,
.pageSizes-li {
margin: 0 15px;
font-size: 12px;
border: none;
}
.pageSizes-li {
border-radius: 5px;
padding: 0 20px;
border: 1px solid rgb(64, 158, 255) !important;
position: relative;
}
.pageSizes {
position: absolute;
width: 100%;
top: 0;
left: 0;
background-color: #eee;
z-index: 1;
border: 1px solid #fff;
}
.disabled {
background-color: #eee;
}
</style>
<YuPagination
:currentPage.sync='currentPage'
:total.sync='total'
:pageSize.sync='pageSize'
:pageSizes='pageSizes'
@currentChange='changeCurrentPage'
@pageSizeChange='pageSizeChange'
/>
data() {
return {
currentPage:1,
total:200,
pageSize:10,
pageSizes:[10,15,20,30]
};
},
methods: {
changeCurrentPage(){
console.log(this.currentPage);
},
pageSizeChange(){
console.log(this.pageSize);
},
}
export const propsType = {
total: {
type: Number,
default:30,
},
currentPage: {
type: Number,
default:1
},
pageSize: {
type: Number,
default:10
},
pageSizes: {
type: Array,
default:()=>[10,15,20,25]
},
disabled: {
type: Boolean,
default:false
},
preClick: {
type: Function,
default:()=>{}
},
nextClick: {
type: Function,
default:()=>{}
},
pagerCount: {
type: Number,
default:7
}
}
实现的功能
- 切换页数时触发的用户传入事件
- 改变页码限制时触发用户传入的事件
- 点击前一页按钮和后一页按钮触发props传入的事件
效果展示
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/09e70df28a6ed82e143422fec3465d0a.gif)
后续可以优化的
- 抽离CSS
- 让用户传入一些属性来动态渲染分页组件的样式:例如大小,颜色