Vue实战028:功能完善的分页组件实现详解

分页在网站中用的比较频繁,现在很多人都喜欢使用第三方组件来快速实现功能,却忽略了其实现原理。这几天抽时间写了个分页组件,功能比较完善,主要包含以下功能:

1,总页数和数据条数

2,可调整显示页码的个数

3,上下和首尾页切换

4,可调整每页显示数据的个数

5,输入指定页面跳转(包括键盘事件(Enter键直接跳转)),限制数据最大不得超过显示页数。

6,当前页为首个或者最后一个时禁止首尾页和上下页选项

 创建模板

首先我们还是先来创建HTML模板,模板中:class="{'disabled': current == 1}"是绑定的DOM类,@click="setCurrent(1)绑定的是点击事件,@keyup.enter="submit($event)"绑定的是键盘事件,:style="{width:'28px'}"绑定的是样式。

<template>
    <nav>
        <span class="pageinfo">共<em>{{pagesum}}</em>页/{{total}}条</span>
        <ul class="pagesumnav">
            <li :class="{'disabled': current == 1}" @click="setCurrent(1)">首页</li>
            <li :class="{'disabled': current == 1}" @click="setCurrent(current-1)">上一页</li>
            <li v-for='(num,id) in grouplist' :key='id' @click="setCurrent(num)" :class="{'actived':(current==num)}" :style="{width:'28px'}">{{num}}</li>
            <li :class="{'disabled': current == pagesum}" @click="setCurrent(current+1)">下一页</li>
            <li :class="{'disabled': current == pagesum}" @click="setCurrent(pagesum)">尾页</li>
        </ul>
        <div class="pagesumjump">
            <select class="pageSelect" @change="pageNum">
                <option v-for="(num,ide) in dispaly" :key="ide">{{num}}条/页</option>
            </select>
            <input type="text" v-model="jumpDefault" @keyup.enter="submit($event)" >
            <span @click="jumpTo">跳转</span>
        </div>
    </nav>
</template>

CSS样式编写

这里就不多阐述了,自己看代码吧,这个应该难不倒大家,主要说下动态的样式:class="{'actived':(current==num)}",在模板中我们绑定了动态样式actived,主要是为了实现当我们点击对应的页码时将背景色及字体颜色更换,让用户一眼就能知道当前在哪页,提供更好的用户体验。还有一个就是:class="{'disabled': current == 1}"样式,这个是用来禁用鼠标事件的。

<style scoped>
.pageinfo em{
    font-style: normal;
    color:#CA0C16;
    padding:2px;
}
.pagesumjump .pageSelect{
    padding:4px;
    height:29px;
    border:none;
    outline: none;
    background-color:#ccc;
}
.pagesumjump input{
    text-align: center;
    width:30px;
    height: 29px;
    margin-left: 3px;
}
.pagesumjump span{
    margin-left: 5px;
    padding:0 6px;
    background-color:#ccc;
    border-radius: 3px;
    cursor: pointer;
    height: 29px;
    line-height: 29px;
    display: inline-block;
}
.pagesumjump span:hover{
    background-color: #CA0C16;
    color:#fff;
}
.disabled{
     pointer-events: none;
}
.actived{
    background-color: #CA0C16;
    color:#fff;
}
nav{
    margin-top:10px;
    display: flex;
    justify-content: center;
    align-items: center;
}
.pagesumnav{
    display: flex;
    justify-content: center;
    align-items: center;
}
.pagesumnav li{
    display: inline-block;
    border:1px solid #ccc;
    border-radius: 2px;
    padding:4px;
    margin:0 2px;
    cursor: pointer;
    -webkit-user-select:none; 
    -moz-user-select:none; 
    -ms-user-select:none; 
    user-select:none;
}
.pagesumnav li:hover{
    background-color: #CA0C16;
    color:#fff;
}
</style>

功能逻辑实现(重点)

下面是功能的实现,要实现分页功能,我们需要知道我们共有多少条数据,每页显示多少条数据,有多少个分页,显示多少个分页,当前在哪等,给父级修改的我们只需要提供这几个参数:数据总条数、每页显示条数、显示页码数,同时我们需要定义当前页参数(默认为1),显示条数(默认10条),跳转页(默认第1页)

props:{
    total:{// 数据总条数
        type:Number,
        default:10,
    },
    dispaly:{// 每页显示条数
        type:Array,
        default(){
            return [10,20,30,50]
        }
    },
    pagegroup:{// 显示页码个数
        type:Number,
        default:5,
    },
},
data(){
    return{
        current: 1,//当前页码
        currentSize:this.dispaly[0],//当前显示条数,默认10条
        jumpDefault:1, //跳转默认值
    }
}

拿到以上几个参数我们开始计算其他数据,接着我们需要知道总共有多少页,根据当前页显示所需的页码。当总页数小于显示页码数时直接显示即可,当当总页数大于显示页码数时我们就需要对当前页进行判断:

当前页在显示页中间的左边时将中心位置移至中间(即处理最前面几个值),当当前页在显示页中间的右边时将中心位置移至中间(即处理最后几个值的)。

computed:{
    pagesum(){  // 根据数据的条数和每页显示数量算出总页数,如果没有则为1 ;
        return Math.ceil(this.total/this.currentSize) ||1
    },
    grouplist(){ //获取分页码
        var len=this.pagesum
        var count=Math.floor(this.pagegroup/2)
        var center =this.current
        var temp=[]
        if(len<this.pagegroup){
            while(len--){
                temp.push(this.pagesum-len)
            }
            return temp
        }
        while(len--){
            temp.push(this.pagesum-len)
        }
        var idx = temp.indexOf(center);
        if(idx<=count){
            center=center+count-idx
        }else if(idx>this.pagesum-count-1){
            center=this.pagesum-count
        }
        var temp=temp.splice(center-count-1,this.pagegroup)
        return temp
    }
},

监听input框参数,当输入的值大于当前的总页数时只显示总页数值,避免超程现象出现。

watch:{
    jumpDefault(){
        if(this.jumpDefault>=this.pagesum){
            this.jumpDefault=this.pagesum
        }
    }
},

接下来是页面跳转功能的实现了,pageNum获取我们切换显示数据条数参数,将值赋给currentSize并重置jumpDefault参数和选择页面,setCurrent(idx)跳转页面并将当前页和分页显示数传给父组件。jumpTo跳转按钮功能实现,submit($event)为键盘监听事件。

methods:{
    pageNum(){ //切换显示条数
        let nums=document.getElementsByClassName('pageSelect')[0].value
        var num=nums.split('条')[0]
        this.currentSize=num
        this.jumpDefault=1
        this.setCurrent(1)
    },
    setCurrent(idx){
        // 判断当前页码不等于本身,和大于零,而且要小于总页数的时候,才触发
        if (this.current != idx && idx > 0 && idx < this.pagesum + 1) {
            this.current = idx;
        }
        this.$emit('pagedata',{currentpage:this.current,currentSize:this.currentSize})
    },
    jumpTo(){
            this.current=parseInt(this.jumpDefault)
            this.setCurrent(this.current)
    },
    submit($event){
        this.jumpTo()
    }
}

父组件调用

到这里我们的功能就基本实现了,现在我们在父组件中调用子组件并模拟些数据来测试下效果,因为我子组件传参都给了默认值,所以这里我只传了关键参数:total="num",并监听子组件传回来的数据@pagedata="getpagedata"。

#HTML
<ul class="articalList">
    <li v-for="(artical,ide) in articalList" :key="ide">{{artical}}</li>
</ul>
<PageNav @pagedata="getpagedata" :total="num"></PageNav>
#JavaScript
import PageNav from '@/components/pagenav'
created(){
    for(let i = 0; i<300 ; i++){
        this.temp.push('this is Page design test database : '+i)
    }
},
computed:{
    num(){
        let num =this.temp.length
        return num
    }
},
components:{
    PageNav,
},
methods:{
    getpagedata(data){
        var current=data.currentpage
        var size=data.currentSize
        this.articalList=this.temp.slice((current-1)*size,current*size)
    }
}

通过getpagedata(data)方法拿到子组件中传回来的当前页和每页显示的数据个数,接着把现实数据筛选出来并赋给循环列表即可将数据渲染出来,下面是显示结果。

这是完整组件,有兴趣的可以下载参考:    https://download.youkuaiyun.com/download/kevinfan2011/11253158 

欢迎关注本人的公众号:编程手札,文章也会在公众号更新

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ProgramNotes

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值