@[toc]
27.分页器静态组件(难点)
难点:
考虑点1:为啥需要分页呢?
答案:按需加载
考虑点2:分页器展示,需要哪些数据(条件)?
答案:需要知道4个参数:pageNo、pageSize、total、continues
考虑点3:为啥continues大多都是奇数个数?
答案:因为对称且好看。
考虑点4:为啥不直接使用ElementUI啥的第三方组件呢?
答案:咱自己要掌握自定义分页功能,因为万一产品经理想要自定义分页规则呢。
考虑点5:如何设计分页器原理?(最难点)
- 知道当前第几页:pageNo
- 知道分页器一共需要展示多少条数据:total
- 知道每一页需要展示数据个数:pageSize
- 知道连续的页码数,比如连续页面为: 5 6 7 8 9
- 知道可能发生错误的地方:比如当总页数没有连续页码多时如何处理;再比如连续页码比总页数多算正常现象情况下,但是pageNo为【1|2】的时候,那么start就会出现【0|负数】,或者pageNo为【totalPage | totalPage-1】的时候,那么就会出现end > totalPage。这又该如何处理。
- 知道"..."不加点击事件。
- 知道【第二页...、倒数第二页...】需要加v-if判断,控制显隐。
考虑点6:分页组件要注册成为全局组件,因为好多地方会使用它
修改代码:
src/main.js
//全局注册分页组件
import Pagination from '@/components/Pagination'
Vue.component(Pagination.name, Pagination)
src/components/Pagination/index.vue
<template>
<div class="pagination">
<!-- 上 -->
<button :disabled="pageNo == 1" @click="$emit('getPageNo', pageNo - 1)">上一页</button>
<button v-if="startNumAndEndNum.start > 1" :class="{ active: pageNo == 1 }" @click="$emit('getPageNo', 1)">1</button>
<button v-if="startNumAndEndNum.start > 2">···</button>
<!-- 中间部分,注意:v-for遍历数字索引从1开始,由于添加规则page >= startNumAndEndNum.start,所以最终显示的只有continues个数字 -->
<button v-for="(page, index) in startNumAndEndNum.end" v-if="page >= startNumAndEndNum.start" :key="index" :class="{ active: pageNo == page }" @click="$emit('getPageNo', page)"
>{
{ page }}</button>
<!-- 下 -->
<button v-if="startNumAndEndNum.end < totalPage - 1">···</button>
<button v-if="startNumAndEndNum.end < totalPage" :class="{active:pageNo==totalPage}" @click="$emit('getPageNo', totalPage)"
>{
{ totalPage }}</button>
<button :disabled="pageNo == totalPage" @click="$emit('getPageNo', pageNo + 1)">下一页</button>
<button style="margin-left: 30px">共 {
{ total }} 条</button>
</div>
</template>
<script>
export default {
name: "Pagination",
props: ["pageNo", "pageSize", "total", "continues"],
computed: {
//总共多少页
totalPage() {
//向上取证
return Math.ceil(this.total / this.pageSize);
},
//计算出连续的页码的起始数字与结束数字[连续页码的数字:至少是5]
startNumAndEndNum() {
//解构出来,不解构是作为实例身上的属性,不解构没法用,所谓解构:就是要将对象分解为多个属性,这个对象可以是this对象也可以是普通的对象
const {continues, pageNo, totalPage} = this;
//先定义两个变量存储起始数字与结束数字
let start = 0, end = 0;
//连续页码数字5【就是至少五页】,如果出现不正常的现象【就是不够五页】
//不正常现象【总页数没有连续页码多】
if (continues > totalPage) {
start = 1;
end = totalPage;
} else {
//正常现象【连续页码5,但是你的总页数一定是大于等于5的】
//起始数字,注意:parseInt()方法是向下取整
start = pageNo - parseInt(continues / 2);
//结束数字
end = pageNo + parseInt(continues / 2);
//把出现不正常的现象【start数字出现0|负数】纠正,假设pageNo为【1|2】的时候,那么start就会出现【0|负数】
if (start < 1) {
start = 1;
end = continues;
}
//把出现不正常的现象[end数字大于总页码]纠正,假设pageNo为【totalPage | totalPage-1】的时候,那么就会出现end > totalPage
if (end > totalPage) {
end = totalPage;
start = totalPage - continues + 1;
}
}
return {start, end};
},
},
};
</script>
<style lang="less" scoped>
.pagination {
text-align: center;
button {
margin: 0 5px;
background-color: #f4f4f5;
color: #606266;
outline: none;
border-radius: 2px;
padding: 0 4px;
vertical-align: top;
display: inline-block;
font-size: 13px;
min-width: 35.5px;
height: 28px;
line-height: 28px;
cursor: pointer;
box-sizing: border-box;
text-align: center;
border: 0;
&[disabled] {
color: #c0c4cc;
cursor: not-allowed;
}
&.active {
cursor: not-allowed;
background-color: #409eff;
color: #fff;
}
}
}
.active {
background: skyblue;
}
</style>
src/pages/Search/index.vue
<!-- 分页器 -->
<Pagination
:pageNo="searchParams.pageNo"
:pageSize="searchParams.pageSize"
:total="total"
:continues="5"
@getPageNo="getPageNo"
/>
import {mapGetters, mapState} from "vuex"
methods: {
//自定义事件的回调函数---获取当前第几页
getPageNo(pageNo) {
//整理带给服务器参数
this.searchParams.pageNo = pageNo;
//再次发请求
this.getData();
}
}
computed:{
//获取search模块展示产品一共多少数据
...mapState({
total: (state) => state.search.searchList.total,
}),
}
问题1:为啥需要分页呢?
答案:按需加载
问题2:分页器展示,需要哪些数据(条件)?
答案:自定义分页器前,需要知道4个参数:
- pageNo:代表当前第几页
- pageSize:代表每一页展示多少条数据
- total:代表数据总条数
- continues:代表分页连续页码个数
问题3:为啥continues大多都是奇数个数?
答案:因为对称且好看。比如淘宝的分页器,中间7-11是奇数个。
问题4:为啥不直接使用ElementUI啥的第三方组件呢?
答案:咱自己要掌握自定义分页功能,因为万一产品经理想要自定义分页规则呢。
问题5:如何设计分页逻辑?(最难点)
答案:考虑start和end的实现逻辑,以及vue模板中的判断逻辑。
computed: {
//总共多少页
totalPage() {
//向上取证
return Math.ceil(this.total / this.pageSize);
},
//计算出连续的页码的起始数字与结束数字[连续页码的数字:至少是5]
startNumAndEndNum() {
//解构出来,不解构是作为实例身上的属性,不解构没法用,所谓解构:就是要将对象分解为多个属性,这个对象可以是this对象也可以是普通的对象
const {continues, pageNo, totalPage} = this;
//先定义两个变量存储起始数字与结束数字
let start = 0, end = 0;
//连续页码数字5【就是至少五页】,如果出现不正常的现象【就是不够五页】
//不正常现象【总页数没有连续页码多】
if (continues > totalPage) {
start = 1;
end = totalPage;
} else {
//正常现象【连续页码5,但是你的总页数一定是大于等于5的】
//起始数字,注意:parseInt()方法是向下取整
start = pageNo - parseInt(continues / 2);
//结束数字
end = pageNo + parseInt(continues / 2);
//把出现不正常的现象【start数字出现0|负数】纠正,假设pageNo为【1|2】的时候,那么start就会出现【0|负数】
if (start < 1) {
start = 1;
end = continues;
}
//把出现不正常的现象[end数字大于总页码]纠正,假设pageNo为【totalPage | totalPage-1】的时候,那么就会出现end > totalPage
if (end > totalPage) {
end = totalPage;
start = totalPage - continues + 1;
}
}
return {start, end};
},
},
注意点6:计算总共多少页,可以采用Math.ceil(this.total / this.pageSize)向上取整的方式。
注意点7:只有数字的页码才添加点击事件,针对页码为...的不添加点击事件,只会新增v-if判断。
<button v-if="startNumAndEndNum.start > 1" :class="{ active: pageNo == 1 }" @click="$emit('getPageNo', 1)">1</button>
<button v-if="startNumAndEndNum.start > 2">···</button>
<button v-if="startNumAndEndNum.end < totalPage - 1">···</button>
<button v-if="startNumAndEndNum.end < totalPage" :class="{active:pageNo==totalPage}" @click="$emit('getPageNo', totalPage)"
注意点8:<button :disabled="pageNo == 1",其中disabled用来控制是否禁用,就是不可点击的意思。
注意点9:子组件传父组件通信,使用自定义事件,除了使用this.\$emit方式外,也可以在标签中采用@click="\$emit('getPageNo', 1)"方式。
注意点10::class="{ active: pageNo == 1 }"用来标识哪个分页按钮高亮。
注意点11:中间部分,注意:v-for遍历数字索引从1开始,由于添加规则page >= startNumAndEndNum.start,所以最终显示的只有continues个数字。
<button v-for="(page, index) in startNumAndEndNum.end" v-if="page >= startNumAndEndNum.start" :key="index" :class="{ active: pageNo == page }" @click="$emit('getPageNo', page)"
>{
{ page }}</button>
注意点12:代码解构,不解构是作为实例身上的属性,不解构没法用,所谓解构:就是要将对象分解为多个属性,这个对象可以是this对象也可以是普通的对象。
const {continues, pageNo, totalPage} = this;
注意点13:方法是可以返回多个参数的,采用{}方式返回即可实现。
return {start, end};
本人其他相关文章链接
1.vue尚品汇商城项目-day04【24.点击搜索按钮跳转后的页面商品列表、平台售卖属性动态展示(开发Search组件)】
2.vue尚品汇商城项目-day04【25.面包屑处理关键字】
3.vue尚品汇商城项目-day04【26.排序操作(难点)】
4.vue尚品汇商城项目-day04【27.分页器静态组件(难点)】
5.vue尚品汇商城项目-day04【28.详情页面Detail】
6.vue尚品汇商城项目-day04【29.加入购物车操作(难点)】