手写封页组件,类似于element的组件封页,只需要传入,总数量,和每页显示数量便可以使用,还可以控制按钮的显示
首先先把静态结构写入
html ,css
<template>
<div class="pagination">
<a href="javascript:;" class="disabled">上一页</a>
<span>...</span>
<a href="javascript:;" class="active">3</a>
<a href="javascript:;">4</a>
<a href="javascript:;">5</a>
<a href="javascript:;">6</a>
<a href="javascript:;">7</a>
<span>...</span>
<a href="javascript:;">下一页</a>
</div>
</template>
<script>
export default {
name: 'XtxPagination'
}
</script>
<style scoped lang="less">
pagination {
display: flex;
justify-content: center;
padding: 30px;
> a {
display: inline-block;
padding: 5px 10px;
border: 1px solid #e4e4e4;
border-radius: 4px;
margin-right: 10px;
&:hover {
color:#a7df73;
}
&.active {
background:#a7df73;
color: #fff;
border-color:#a7df73;
}
&.disabled {
cursor: not-allowed;
opacity: 0.4;
&:hover {
color: #333
}
}
}
> span {
margin-right: 10px;
}
}
</style>
下面开始讲解实现逻辑
首先的话肯定是需要接收到传入的props ,包含了总条数,默认显示页(这个是因为我这边又筛选,筛选的话是需要重置页码为1的,所有需要这个参数),每页条数,按钮个数(按钮个数就是显示几个页码)
props: {
total: {
type: Number,
default: 100,
},
currentPage: {
type: Number,
default: 1,
},
pageSize: {
type: Number,
default: 10,
},
btnCount: {
type: Number,
default: 5,
},
},
拿到了总条数,和每页显示的条数,那么就可以算出来一共多少页,这边可以使用计算属性
// 总条数
const myTotal = ref(100);
// 每页条数
const myPageSize = ref(10);
// 当前第几页
const myCurrentPage = ref(6);
// 按钮个数(就是显示多少也前后变为...)
const btnCount = ref(5);
//上面这些数据为什么传值进来了还要再声明一下,下面解释
const pager = computed(() => {
// 计算总页数
const pageCount = Math.ceil(myTotal.value / myPageSize.value)
// 计算起始页码和结束页码
//这边举个简单的例子,因为你激活项也就是当前页需要是在中间的
//这也就是当前的页数减去总按钮的一般,然后先下取整
let start = myCurrentPage.value - Math.floor(btnCount / 2)
//那么起始页是到当前页是一半的话那么当前页到结束页也就是一般,所有就是起始页加上当前按钮个数-1(起始页距离结束页就是按钮的数量所有是起始页加按钮的个数)
let end = start + btnCount - 1
// 2.1 如果起始页码小于1了,需要重新计算
//但是会又其它情况出现,比如当前激活页是1||2那么起始页就会小于1,那么起始页和结束页都需要做出改变
if (start < 1) {
//让起始页变为1
start = 1
//判断起始页+按钮数-1是否大于总页数(因为可能一共就三页的数据)如果大于总页数的话那么直接返回总页数,如果不是的话那么就返回起始页+按钮个数-1
end = (start + btnCount - 1) > pageCount ? pageCount : (start + btnCount - 1)
}
// 2.2 如果结束页码大于总页数,需要重新计算
if (end > pageCount) {
//如果结束页大于了总页数的话那么就等于总页数
end = pageCount
//起始页的话就变为结束页-按钮数量+1(要判断是否大于1,就像上面说的一共三页五个按钮的情况下)
start = (end - btnCount + 1) < 1 ? 1 : (end - btnCount + 1)
}
// 处理完毕start和end得到按钮数组
const btnArr = []
//这里就得到了循环出来的页码值
for (let i = start; i <= end; i++) {
btnArr.push(i)
}
return { pageCount, start, end, btnArr }
})
return { pager, myCurrentPage}
接下里就是进行渲染了
<div class="pagination">
<a v-if="myCurrentPage <= 1" href="javascript:;" class="disabled">上一页</a>
<a @click="changePage(myCurrentPage - 1)" v-else href="javascript:;"
>上一页</a
>
<span v-if="pager.start > 1">...</span>
<a
@click="changePage(i)"
href="javascript:;"
:class="{ active: i === myCurrentPage }"
v-for="i in pager.btnArr"
:key="i"
>{{ i }}</a
>
<span v-if="pager.end < pager.pageCount">...</span>
<a
v-if="myCurrentPage >= pager.pageCount"
href="javascript:;"
class="disabled"
>下一页</a
>
<a @click="changePage(myCurrentPage + 1)" v-else href="javascript:;"
>下一页</a
>
</div>
点击上一页下一页或者页码的时候直接把算好的值传入函数内进行接收,然后触发emit事件给父元素
// 改变页码
//为什么不直接使用props传入的数据呢
//就是因为props的数据是单向流的,你不能直接修改,
//这里是直接拿到了激活页给父组件返回出去了,没法直接拿到新的激活页面
//有点麻烦,需要加入好几个判断
const changePage = (newPage) => {
if (myCurrentPage.value !== newPage) {
myCurrentPage.value = newPage;
// 通知父组件最新页码
emit("current-change", newPage);
}
};
然后监听props的改变就像给自己的数据赋值
watch(
props,
() => {
myTotal.value = props.total;
myPageSize.value = props.pageSize;
myCurrentPage.value = props.currentPage;
btnCount.value = props.btnCount;
},
{ immediate: true }
);