Vue分页组件的实现

Vue 简单分页

效果

实现效果:

ukFS76.gif

使用

// 在父组件使用
<zeroPagination 
:total="totals" 
:current-page="current" 
@changePage="change_page"
@changePageSize="change_pagesize"  
:page-size="pageSize"
:simple="false"/>

参数

需要的参数为,

totals:数据总数

current-page:当前页

可指定的不必须参数

page-size:每页显示数据条数

返回当前页跟当前显示页数

Pagination.vue

<template>
    <ul id="zero-pagination" v-if="pages!==1 && pages!==0">
        <li :class="current === 1?'disabled':''">
            <a href="javascript:;" @click="prev">
                <i class="fas fa-angle-left"></i>
            </a>
        </li>
        <li v-for="(node,index) in pageNodeList" :class="current === node.value?'active':''" :key="index">
            <a v-if="node.text==='prevMore'"  @click="prev">
                <i class="fas fa-angle-double-left"></i>
            </a>
            <a href="javascript:;" @click="go(node.value)">
                
            </a>     
            <a v-if="node.text==='nextMore'"  @click="next">
                <i class="fas fa-angle-double-right"></i>
            </a> 
        </li>
        <li :class="current === pages?'disabled':''">
            <a href="javascript:;" @click="next">
                <i class="fas fa-angle-right"></i>
            </a>
        </li>
        <li v-if="!simple">
            <a href="javascript:;" @click="first">
                首页
            </a>
        </li>
        <li v-if="!simple">
            <a href="javascript:;" @click="last">
                尾页
            </a>
        </li>
        <li v-if="!simple">
            <select v-model="currentPageSize" @change="setCurrentPageSize">
                <!-- 不动态绑定value会得到一个字符串导致类型检测失败 -->
                <option :value="5" selected>5</option>
                <option :value=10>10</option>
                <option :value=15>15</option>
                <option :value=20>20</option>
            </select>
        </li>
    </ul>
</template>

<script>
/**
 * name:zeroPagination
 * props:{
 *  total:Number
 *  currentPage:Number
 *  pageSize:Number
 *  pageNodes:Number 偶数会强制成奇数
 *  simple:Boolean
 * }
 * Function:{
 *  changePage return current
 *  changePageSize return currentPageSize
 * }
 */
export default {
    name:'zeroPagination',
    data(){
        return{
            // 当前每页显示条数
            currentPageSize:this.pageSize,
            // 当前页
            current:this.currentPage,
            // 总记录数
            size:this.total,
        }
    },
    props:{
        // 数据总数
        total:{type:Number,default:0},
        // 每页显示条数
        pageSize:{type:Number,default:5},
        // 当前页
        currentPage:{type:Number,default:1},
        // 可见页码数
        pageNodes:{
            // 指定分页项目最多个数
            type:Number,
            default:4,
            // 强制转换为奇数
            coerce:(v)=>{
                v=v>0?v:10;
                return v % 2 === 1?v:v+1;
            }
        },
        simple:{
            type:Boolean,
            default:false
        }
    },
    computed:{
        // 总页数
        pages:function(){
            return Math.ceil(this.size/this.currentPageSize);
        },
        // 分页页码
        pageNodeList:function(){
            // 页码个数
            const page_node_number = this.pageNodes;
            // 总页数
            const page_count = this.pages;
            // 当前页
            let current_page = this.current;
            // 偏移量
            const _offset = Math.floor(page_node_number/2);
            const offset = {
                start : current_page - _offset,
                end: current_page + _offset,
            }

            let list = [];

            if(offset.start < 1){
                offset.end = offset.end + (1 - offset.start);
                offset.start = 1;
            }
            if(offset.end > page_count){
                offset.start = offset.start - (offset.end - page_count);
                offset.end = page_count;
            }
            if(offset.start < 1){
                offset.start = 1
            }

            for(let i = offset.start; i <= offset.end;i++){
                list.push({
                    text:i,
                    value:i
                });
            }
            let tempList = [];
            if(offset.start > 1){
                tempList.push({
                    text:'prevMore',
                    value:''
                })
            }
            list.forEach(item=>tempList.push(item));
            if(offset.end < page_count){
                tempList.push({
                    text:'nextMore',
                    value:''
                })
            }
            return tempList;
        }
    },
    methods:{
        setCurrentPageSize(){
            this.$emit('changePageSize',this.currentPageSize);
        },
        prev(){
            if (this.current > 1) {
                this.go(this.current - 1)
            }
        },
        next(){
            if (this.current < this.pages) {
                this.go(this.current + 1)
            }
        },
        first(){
            if (this.current !== 1) {
                this.go(1)
            }
        },
        last(){
            if (this.current != this.pages) {
                this.go(this.pages)
            }
        },
        go (page) {
            if (this.current !== page) {
                this.current = page
                //父组件通过change方法来接受当前的页码
                this.$emit('changePage',this.current);
            }
        }
    },
    watch:{
        currentPage(val) {
            this.current = val || 1
        },
        pageSize(val) {
            this.currentPageSize = val || 5
        },
        total(val) {
            this.size = val || 0
        },
        currentPageSize(){
            // 监听改变每页显示数
            let pages = Math.ceil(this.size / this.currentPageSize);
            if (this.currentPage > pages) {
                this.current = pages;        
                this.$emit('changePage',this.current);
            }
        }
    }
}
</script>

<style>
#zero-pagination {
    margin-top: 20px;
    text-align: center;
    overflow: hidden;
    display: table;
    margin: 0 auto;
    height: 50px;
}
#zero-pagination li{
    height: 25px;
    line-height: 25px;
    color: #757575;
    text-align: center;
    text-decoration: none;
    display: inline-block;
    margin: 0 8px;
}
#zero-pagination a{
    color: #757575;
}
#zero-pagination li.disabled{
    display: none;
}
</style>

重点

依然是数据驱动,需要使用分页的父组件拥有一个数据列表,需要进行分页显示。

我们拥有的数据就是后台传递的数据总数,当前页。

传递给分页组件,监听当前页,总数,等基本的数据进行分页内数据的逻辑处理。

包括返回首页和到达尾页,

根据指定的显示多少页码来计算偏移量显示省略图标。

// 分页页码
pageNodeList:function(){
    // 页码个数
    const page_node_number = this.pageNodes;
    // 总页数
    const page_count = this.pages;
    // 当前页
    let current_page = this.current;
    // 偏移量
    const _offset = Math.floor(page_node_number/2);
    const offset = {
        start : current_page - _offset,
        end: current_page + _offset,
    }
    // 储存 可渲染的页码
    let list = [];
    if(offset.start < 1){
        offset.end = offset.end + (1 - offset.start);
        offset.start = 1;
    }
    
    if(offset.end > page_count){
        offset.start = offset.start - (offset.end - page_count);
        offset.end = page_count;
    }
    
    if(offset.start < 1){
    	offset.start = 1
    }

    for(let i = offset.start; i <= offset.end;i++){
        list.push({
            text:i,
            value:i
        });
    }
    // 转换成带省略的数组
    let tempList = [];
    // 存在超出的部分添加如一个标志对象
    if(offset.start > 1){
        tempList.push({
            text:'prevMore',
            value:''
    	})
    }
    list.forEach(item=>tempList.push(item));
    if(offset.end < page_count){
        tempList.push({
            text:'nextMore',
            value:''
            })
    }
    return tempList;
}


奖励一下