我要造轮子系列 - 常用的分页组件

前言

分页组件也前端高频组件,但一般用在pc端,移动端出现比较少,因为按照移动端使用习惯在移动端通常会使用下拉加载刷新或者上拉加载刷新 这次编写的组件也是针对pc端。分页组件目的为了方便浏览通常将服务器响应回来的大量数据做分页
从实现方式上来说分页基本分为两种方式:

1.查询所有数据返回给客户,通过显示指定区间实现分页,这种方法一般是指JS分页

2.通过客户发送的请求,构造sql语句,查询表中的一段数据。

分页组件效果

屏幕录制2021-06-29 下午5.58.08.gif

分页组件需求分析

1.总数据量,一般传入后端返回的数据总数字段

2.每页实际条数,传入自定数值

3.每页要显示条数,传入自定的数值,比如每页条数的是10条,在10条之间显示5条

4.总共多少页的计算公式是 总数据量/每页要显示条数

5.点击下一页,上一页改变current 点击首页跳转第一页,点击尾页跳转到最尾一页,判断如果第一页和最尾一页设置禁止点击首页、下一页、上一页、尾页按钮

6.input框输入限制1 - 总数量的输入,设置数值跳转到当前页

7.currentCallBack点击返回当前索引

8.传入color可以自定喜欢的颜色

9.每页显示的条数计算,用vue的watch来监听current值的变化 ,然后通过当前的current计算出实际显示那几页出来,计算方式如下

 watch: {
            current(newVal) {
                let temp = [],
                    max,
                    min = newVal - Math.floor(this.pageNum / 2)
                if (min < 1) min = 1
                max = min + this.pageNum - 1
                if (max > this.pageTotalNum) max = this.pageTotalNum
                for (let i = min; i <= max; i++) {
                    temp.push(i)
                }
                this.pageSizeNum = temp
            }
        },

props参数

参数 说明 类型 默认值
page-total 总数据 Number 100
page-num 要显示页数 Number 10
page-size 分页大小 Number 5
color 传入的主题颜色 Number #409eff
currentCallBack 返回点击的当前索引值 Events

完整代码

<template>
    <div class="_page_container">
        <ul class="_pages _pages_1">
            <li :class="['_home', setFristDisabled]" @click.prevent="setHomePageination">首页</li>
            <li :class="['_prev_ _prev' ,setFristDisabled]" @click="prevPageination">上一页</li>
            <li :class="['_pages_li_1',getCurrent(item)?'_active_1':'']"
                :style="{backgroundColor : getCurrent(item) ? color : ''}"
                :data-index="item"
                v-for="(item) in pageSizeNum"
                :key="item"
                @click.prevent="switchPageination(item)"
            >{{item}}
            </li>
            <li :class="['_next_ _next', setLastDisabled]"
                @click.prevent="nextPageination">下一页
            </li>
            <li :class="['_last', setLastDisabled]"
                @click="setLastPageination">尾页
            </li>
        </ul>
        <div class="_jumper">
            <span class="_count">共 {{pageTotalNum}} 页</span>
            <span>前往</span>
            <label>
                <input class="_jumper_input"
                       type="number"
                       min="1"
                       :max="pageTotalNum"
                       @blur="jumpPageination($event)"
                       @keyup.enter="jumpPageination($event)"/>
            </label>
            <span>页</span>
        </div>
    </div>
</template>

<script>
    export default {
        name: 'pagination',
        props: {
            // 总数据
            pageTotal: {
                type: Number,
                default: 100
            },
            // 实际分页大小
            pageSize: {
                type: Number,
                default: 10
            },
            //显示页数
            pageNum: {
                type: Number,
                default: 5
            },
            //自定义颜色
            color: {
                type: String,
                default: '#409eff'
            }
        },
        data() {
            return {
                current: 1,
                pageSizeNum: Array.from({length: this.pageNum}, (_, index) => index + 1),
                pageTotalNum: Math.ceil(this.pageTotal / this.pageSize)
            }
        },
        computed: {
            getCurrent() {
                return (index) => {
                    return this.current === index
                }
            },
            setFristDisabled() {
                return this.current === 1 ? '_disabled_c _disabled' : ''
            },
            setLastDisabled() {
                return this.current === this.pageTotalNum ? '_disabled_c _disabled' : ''
            }
        },
        watch: {
            current(newVal) {
                let temp = [],
                    max,
                    min = newVal - Math.floor(this.pageNum / 2)
                if (min < 1) min = 1
                max = min + this.pageNum - 1
                if (max > this.pageTotalNum) max = this.pageTotalNum
                for (let i = min; i <= max; i++) {
                    temp.push(i)
                }
                this.pageSizeNum = temp
            }
        },
        updated() {
            this.$emit('currentCallBack', this.current - 1)
        },
        methods: {
            switchPageination(index) {
                this.current = index
            },
            nextPageination() {
                if (this.current === this.pageTotalNum) {
                    this.current = this.pageTotalNum
                }else {
                    this.current++
                }
            },
            prevPageination() {
                if (this.current === 1) {
                    this.current = 1
                }else {
                    this.current--
                }
            },
            setHomePageination() {
                this.current = 1
            },
            setLastPageination() {
                this.current = this.pageTotalNum
            },
            jumpPageination(ev) {
                let value = Number(ev.currentTarget.value)
                if (value < 1) value = 1
                if (value > this.pageTotalNum) value = this.pageTotalNum
                this.current = value
            }
        }
    }
</script>

<style scoped>


    ._page_container {
        height: 28px;
        line-height: 28px;
        text-align: center;
        user-select: none;

    }

    ._page_container input[type=number] {
        -moz-appearance: textfield;
    }

    ._page_container input[type=number]::-webkit-inner-spin-button,
    ._page_container input[type=number]::-webkit-outer-spin-button {
        -webkit-appearance: none;
        margin: 0;
    }

    ._page_container ._pages {
        display: inline-block;
    }

    ._page_container ._pages li {
        display: inline-block;
        list-style: none;
        vertical-align: top;
        color: #303133;
        font-weight: bold;
        min-width: 30px;
        text-align: center;
        margin: 0 5px;
        border-radius: 2px;
        cursor: pointer;
    }

    ._page_container ._pages li:hover {
        opacity: .6;
        transition-duration: 500ms;
        transition-timing-function: ease;
    }

    ._page_container ._pages li:first-child, ._page_container ._pages li:last-child {
        font-size: 14px;
    }

    ._page_container ._pages ._prev, ._page_container ._pages ._next, ._page_container ._pages ._home, ._page_container ._pages ._last {
        font-size: 12px;
        font-weight: normal;
        padding: 0 8px;
    }

    ._page_container ._jumper {
        display: inline-block;
        color: #606266;
        margin-left: 10px;
    }

    ._page_container ._jumper ._count {
        margin-right: 10px;
    }

    ._page_container ._jumper ._jumper_input {
        display: inline-block;
        font-size: 14px;
        color: #606266;
        width: 50px;
        height: 26px;
        text-align: center;
        margin: 0 5px;
        padding: 3px;
        border: 1px solid #dcdfe6;
        border-radius: 4px;
        background: none;
        outline: none;
        box-sizing: border-box;
    }

    ._page_container ._jumper ._jumper_input:focus {
        border-color: #409eff;
        transition-duration: 500ms;
        transition-timing-function: ease;
    }

    ._pages_1 li {
        background-color: #f4f4f5;
    }

    ._active_1 {
        color: #fff !important;
        transition-duration: 500ms;
        transition-timing-function: ease;
    }

    ._active_2 {
        color: #409eff !important;
    }

    ._disabled {
        cursor: not-allowed !important;
    }

    ._disabled_c {
        color: #c0c4cc !important;
    }

</style>

最后

我要造轮子系列的分页组件也完成了,希望同学们有空余时间也多写写,大家一起学习、一起进步,共勉!!

npm

npm install nigo-vue-pagination

yarn

yarn add nigo-vue-pagination

github

git clone https://github.com/shinewen189/nigo-vue-pagination.git

我要造轮子系列文章

【1】.我要造轮子系列-一个轮子的诞生过程

【2】.我要造轮子系列-常用的拖拽组件

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。