原生js实现分页组件开发(一)

分页组件

功能需求:

  1. 根据数据内容,按照每页显示固定数量的内容,完成页面布局;
  2. 根据数据内容,自动创建页码内容;
  3. 点击页码时,完成每页显示固定数量内容的翻页效果;
  4. 每页显示的内容数量可以自定义;
  5. 当显示第一页时,上一页按钮不能点击;当显示最后一页时,下一页按钮不能点击;

来看一下效果:
原生js实现分页组件开发
分析:

  • 因为页码是自动创建的,无法对页码元素进行事件监听,只能使用事件委托来做;
  • 当点击页码后,要考虑三个操作,一是页码的显示状态,二是页面中内容的显示,三是上一页按钮跟下一页按钮的显示状态和点击状态;
  • 点击页码后,先将页面中的内容清除,再放入新的内容;
  • 由于使用了事件委托机制,在点击的时候,需要确定当前操作的元素是页码还是上下页按钮;
  • 当数据内容较多时,页码内容可以做成轮播图的效果,或者将中间部分页码以 省略号 的形式来显示,这个功能暂时还没有实现,大家可以自己做一下。

下面附上代码:

html结构:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>page</title>
</head>
<body>
    <script type="module">
        import Main from "./js/Main.js";
        
        init();
        function init(){
            //第一个参数为每一页要展示的数量,不传默认是50,第二个参数为一共有多少数据,不传默认是143
            let main=new Main(50,305);
            main.appendTo("body");
        }
    </script>
</body>
</html>

Main.js文件:用来创建页面中要显示的内容。

import Utils from './Utils.js';
import Page from './Page.js';
export default class Main{   
    resultData=[];
    content;
    static GET_RESULT_DATA="get_result_data";
    constructor(_num,_dataLength){
        //监听事件,初始化页面内容
        document.addEventListener(Main.GET_RESULT_DATA,e=>this.getResultData(e));
        //创建外层div
        this.elem=this.createElem();
        //实例化页码
        let page=new Page(_num,_dataLength);
        Utils.appendTo(page.elem,this.elem);
    }
    createElem(){
        if(this.elem) return this.elem;
        let div=Utils.createE("div")        
        return div;  
    }
    appendTo(parent){
        Utils.appendTo(this.elem,parent);
    }  
    getResultData(e){
        //获取传递过来的数据
        this.resultData=e.data;
        //创建页面内容
        this.createCont();
    } 
    createCont(){
        //如果页面中已经有内容,则先清除内容,再放入新的内容
        if(this.content) this.content.remove();
        //创建content容器
        this.content=Utils.createE("div",{
            width:"500px",
            height:"250px",
            border:"1px solid #000",
        });
        //根据resultData,创建每一页要显示内容
        this.resultData.forEach(item=>{
            let span=Utils.createE("span",{
                display:"inline-block",
                width:"50px",
                height:"50px",
                textAlign:"center",
                lineHeight:"50px"
            },{
                textContent:item
            })
            Utils.appendTo(span,this.content);
        })
        //插入在页码容器的前面
        this.elem.insertBefore(this.content,this.elem.firstElementChild)
    }
}

Page.js文件:按照数据生成页码,完成对页码的点击操作。

import Utils from "./Utils.js";

export default class Page{
    num;//每一页的数量
    dataLength;//一共有多少数据
    position=1;//表示当前第几页
    pageList=[];//页码的数组
    nextClickBool=false;//控制下一页按钮是否能点击
    preClickBool=false;//控制上一页按钮是否能点击
    prepPage;
    static stylesCss=false;
    static GET_RESULT_DATA="get_result_data";
    constructor(_num=50,_dataLength=143){
        //参数设置默认值
        this.num=_num;
        this.dataLength=_dataLength;
        //创建外层div
        this.elem=this.createElem();
        //抛发事件,设置页面初始内容
        this.setContent();
    }
    createElem(){
        if(this.elem) return this.elem;
        //外层的div容器
        let div=Utils.createE("div");
        div.className="pageContainer";
        div.innerHTML=`<a href="javascript:void(0)" class="disabled" id="preBtn">&lt;上一页</a>${this.setPageCon()}
        <a href="javascript:void(0)" id="nextBtn">下一页&gt;</a>`;
        //设置样式
        Page.setStyles();
        //获取元素
        Utils.getIdElem(div,this);
        //页码监听点击事件
        div.addEventListener("click",e=>this.clickHandler(e));
        return div;
    }
    appendTo(parent){
        Utils.appendTo(this.elem,parent);
    }
    setPageCon(){
        //设置页码内容
        let str="";
        //计算一共有多少页
        for(let i=0;i<Math.ceil(this.dataLength/this.num);i++){
            str+=`<a href="javascript:void(0)" class="${i===0?'active':''}">${i+1}</a>`
        }
        return str;
    }
    clickHandler(e){
        if(e.target.nodeName!="A") return;
        //获取到只有页码的数组,赋值给this.pageList
        let arr=document.querySelectorAll("a");
        this.pageList=Array.prototype.slice.call(arr).slice(1,arr.length-1);
        //设置this.prepPage默认为第1个按钮
        this.prepPage=this.pageList[this.position-1];
        //判断当前操作的元素
        switch (e.target.innerText){
            case "<上一页":
                if(this.preClickBool) return;
                this.nextClickBool=false;
                this.position--;
                if(this.position<=1) {
                    this.position=1;
                    this.preClickBool=true;
                }
                break;
            case "下一页>":
                if(this.nextClickBool) return;
                this.preClickBool=false;
                this.position++;
                if(this.position>=this.pageList.length){
                    this.position=this.pageList.length;
                    this.nextClickBool=true;
                } 
                break;
            default:
                this.position=Number(e.target.innerText);
                this.preClickBool=false;
                this.nextClickBool=false;
                break;
        }                  
        //设置页码的样式
        this.setPageStyles();
        //设置显示的内容
        this.setContent();
        //设置上一页、下一页按钮的样式
        this.setBtnState();
    }
    setPageStyles(){
        //将上一个点击的页码按钮,移除active样式
        if(this.prepPage) this.prepPage.className="";
        //将当前点击的页码按钮,赋值给this.prePage
        this.prepPage=this.pageList[this.position-1];
        //给当前点击的页面按钮,添加active样式
        this.prepPage.className="active";
    }
    setContent(){
        let resultArr=[];
        for(let i=(this.position-1)*this.num;i<this.position*this.num;i++){
            //如果i大于数据的长度,则不把它添加到resultArr中
            if(i>=this.dataLength) continue;
            resultArr.push(i);
        }
        //抛发事件,设置初始化数据
        let evt=new Event(Page.GET_RESULT_DATA);
        evt.data=resultArr;
        document.dispatchEvent(evt);
    }
    setBtnState(){
        //如果当前是第1页,给上一页按钮添加disabled样式
        if(this.position==1) this.preBtn.className="disabled";
        else this.preBtn.className="";
        //如果当前是最后一页,给下一页按钮添加disabled样式
        if(this.position==this.pageList.length) this.nextBtn.className="disabled";
        else this.nextBtn.className="";
    }
    static setStyles(){
        if(Page.stylesCss) return;
        Page.stylesCss=true;
        Utils.insertCss(".pageContainer",{
            marginTop:"30px"
        })
        Utils.insertCss(".pageContainer a",{
            textDecoration:"none",
            display:"inline-block",
            minWidth:"10px",
            textAlign:"center",
            padding:"5px 10px",
            borderRadius:"7px",
            marginRight:"3px",
            backgroundColor:"#fff",
            color:"#818287",
            border:"1px solid #f6f6f6",
            userSelect:"none"
        })
        Utils.insertCss(".pageContainer a:hover",{
            backgroundColor:"rgba(233,37,56,.3)",
            color:"#fff"
        })
        Utils.insertCss(".pageContainer a.disabled",{
            backgroundColor:"#f2f2f2",
            borderColor:"#d9d9d9",
            color:"#ccc"
        })
        Utils.insertCss(".pageContainer a.active",{
            backgroundColor:"#e92538",
            borderColor:"#e92538",
            color:"#fff",
        })
    }
}

Utils.js文件:是一个工具包文件。

export default class Utils{
    static createE(elem,style,prep){
        elem=document.createElement(elem);
        if(style) for(let prop in style) elem.style[prop]=style[prop];
        if(prep) for(let prop in prep) elem[prop]=prep[prop];
        return elem;
    }
    static appendTo(elem,parent){
        if (parent.constructor === String) parent = document.querySelector(parent);
        parent.appendChild(elem);
    }
    static randomNum(min,max){
        return Math.floor(Math.random*(max-min)+min);
    }
    static randomColor(alpha){
        alpha=alpha||Math.random().toFixed(1);
        if(isNaN(alpha)) alpha=1;
        if(alpha>1) alpha=1;
        if(alpha<0) alpha=0;
        let col="rgba(";
        for(let i=0;i<3;i++){
            col+=Utils.randomNum(0,256)+",";
        }
        col+=alpha+")";
        return col;
    }
    static insertCss(select,styles){
        if(document.styleSheets.length===0){
            let styleS=Utils.createE("style");
            Utils.appendTo(styleS,document.head);
        }
        let styleSheet=document.styleSheets[document.styleSheets.length-1];
        let str=select+"{";
        for(var prop in styles){
            str+=prop.replace(/[A-Z]/g,function(item){
                return "-"+item.toLocaleLowerCase();
            })+":"+styles[prop]+";";
        }
        str+="}"
        styleSheet.insertRule(str,styleSheet.cssRules.length);
    }
    static getIdElem(elem,obj){
        if(elem.id) obj[elem.id]=elem;
        if(elem.children.length===0) return obj;
        for(let i=0;i<elem.children.length;i++){
            Utils.getIdElem(elem.children[i],obj);
        }
    }
}
  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值