vue分页组件实现
作为小白,第一次实现分页功能可是费了好一番功夫,所以记录一下在写vue项目时封装的分页组件思路过程和实现代码。
实现效果
随便手写的基础样式(没眼看,主要讲思路和代码)
开发文档
既然说咱们是要封装一个组件,开发文档是必不可少的,也很简单,记录一下这个组件需要的属性和事件,到时候直接根据接口拿到数据就好了。
属性
属性名 | 含义 | 类型 | 必填 | 默认值 |
---|---|---|---|---|
current | 当前页码 | Number | 否 | 1 |
total | 总数据量 | Number | 否 | 0 |
limit | 页容量 | Number | 否 | 10 |
visibleNumber | 可见页码数 | Number | 否 | 10 |
事件
事件名 | 含义 | 事件参数 | 参数类型 |
---|---|---|---|
pageChange | 页码变化 | 新的页码 | Number |
基础实现
- 模板
- 头尾固定内容
- 中间数字部分使用数组进行循环,后续控制数组里的内容即可
- 样式
- active:当前页面需要高亮显示
- disable:当前页面位于首页/尾页时,上一页,到首页/下一页,到尾页属于无法点击状态
- 逻辑
- 在 props 中定义好需要的属性,加上约束条件,便于使用组件时传入
- 使用 computed 中计算后的数组
<template>
<!-- 只有当页码大于1时才显示 -->
<div class="pager-container" v-if="pageNumber > 1">
<a
:class="{ disable: current === 1 }">|<<</a>
<a
:class="{ disable: current === 1 }"><<</a>
<a
v-for="(n, i) in numbers"
:key="i"
:class="{ active: n === current }"
>{{ n }}</a>
<a
:class="{ disable: current === pageNumber }"
>>></a>
<a
:class="{ disable: current === pageNumber }"
>>>|</a>
</div>
</template>
<style scoped lang="less">
@import "~@/styles/var.less";
.pager-container {
display: flex;
justify-content: center;
margin: 20px 0;
a {
color: @primary;
margin: 0 6px;
cursor: pointer;
&.disable {
color: @lightWords;
cursor: default;
}
&.active {
color: @words;
font-weight: bold;
}
}
}
</style>
<script>
export default {
props: {
// 当前页码
current: {
type: Number,
default: 1,
},
// 总数据量
total: {
type: Number,
default: 0,
},
// 每页限制数据量
limit: {
type: Number,
default: 10,
},
// 最多显示页码数
visibleNum: {
type: Number,
default: 10,
},
},
computed: {
// 当前显示页码
numbers() {
let curVisbleNums = [1,2,3,4,5,6,7,8,9,10];
return curVisbleNums;
},
},
};
</script>
计算属性
最重要的一步也就是我们需要计算出以下关于页码的数据,注意范围边界控制
(这里计算最大值最小值的写法会导致首页和尾页显示不一致的情况)
- 页码总数(至少一页,但如果只有一页则不显示组件)
- 当前显示页码最小值
- 当前显示页码最大值
- 当前显示页码数组(关键一步:从最小值循环到最大值,放入数组)
computed: {
// 页码总数=总数据量/每页限制数据量
pageNumber() {
return Math.ceil(this.total / this.limit);
},
// 当前显示页码的最小值
visibleMin() {
let min = this.current - Math.floor(this.visibleNum / 2);
if (min < 1) {
min = 1;
}
return min;
},
// 当前显示页码的最大值
visibleMax() {
let max = this.visibleMin + this.visibleNum - 1;
if (max > this.pageNumber) {
max = this.pageNumber;
}
return max;
},
// 当前显示页码的数组
numbers() {
let curVisbleNums = [];
for (var i = this.visibleMin; i <= this.visibleMax; i++) {
curVisbleNums.push(i);
}
return curVisbleNums;
},
},
事件处理
最后我们需要注册点击事件来进行改变当前页码的操作
因为vue中单项数据流的特性,我们不能直接在当前组件中进行点击事件,我们要抛出事件给使用这个组件的父组件进行处理
<template>
<!-- 只有当页码大于1时才显示 -->
<div class="pager-container" v-if="pageNumber > 1">
<a @click="changePage(1)" :class="{ disable: current === 1 }">|<<</a>
<a @click="changePage(current - 1)" :class="{ disable: current === 1 }"
><<</a
>
<a
@click="changePage(n)"
v-for="(n, i) in numbers"
:key="i"
:class="{ active: n === current }"
>{{ n }}</a
>
<a
@click="changePage(current + 1)"
:class="{ disable: current === pageNumber }"
>>></a
>
<a
@click="changePage(pageNumber)"
:class="{ disable: current === pageNumber }"
>>>|</a
>
</div>
</template>
methods: {
changePage(newPage) {
if (newPage < 1) {
newPage = 1;
}
if (newPage > this.pageNumber) {
newPage = this.pageNumber;
}
if (newPage === this.current) {
return;
}
// 抛出一个事件让父级处理
this.$emit("pageChange", newPage);
},
},
父组件的逻辑就很简单了,收到子组件提交的事件,进行改变当前页码或者渲染页面等其他处理即可
<template>
<div>
<Pager
:current="current"
:total="total"
@pageChange="handlePageChange"
/>
</div>
</template>
<script>
import Pager from "@/components/Pager";
export default {
data(){
return{
current:1,
total:302
}
},
components: {
Pager,
},
methods:{
handlePageChange(newPage) {
this.current = newPage;
//加载页面操作...
}
}
}
</script>
这个分页组件涵盖了基本的分页功能,仅供参考,还有很多可以地方可以根据需求来改进。