0
点赞
收藏
分享

微信扫一扫

面向对象案例一-分页

typora-copy-images-to: media

面向对象案例一-分页

结构分析:

<div>
    <div class="first">首页</div>
    <div class="prev">上一页</div>
    <div class="list">
        <p>1</p>
        <p>2</p>
        <p>3</p>
        <p>4</p>
        <p>5</p>
    </div>
    <div class="next">下一页</div>
    <div class="last">尾页</div>
</div>

为了好区分每个div,所以每个div都加上类名

页码规律分析:

  1. 总页数小于等于5时,展示页码尾:1~总页数
  2. 总页数大于5时
  • 当前页小于等于3,展示1~5
  • 当前页大于等于总页数-2,展示总页数-4~总页数
  • 其余情况展示当前页-2~当前页+2

代码分析:

代码基本结构

function Page(classname){
    this.box = document.querySelector('.' + classname)
    
}

var page = new Page(".pagination")

参数分析

  1. 上一页、下一页、首页、尾页 这些显示的文字,能满足大部分人的需求,但不能满足所有项目的需求,为了让封装好的插件更具适用性,将这些显示的文字作为参数
  2. 在代码需要用总页数做判断,是需要计算总页数的,公式如下:总页数 = Math.ceil(数据总条数/每页显示的条数),而数据总条数和每页显示的条数又要根据项目的实际情况,也就需要在调用本插件的时候当做参数传传入

由于参数较多,所以将所有参数组成对象传入,即:

function Page(classname,options){
    this.box = document.createElement('div') // 自己创建一个div容器
    // 将创建好的div容器放到预定好的盒子中
    document.querySelector('.' + classname).appendChild(this.box) 
    // 给创建好的div设置样式
    this.setStyle(this.box,{
        display:"flex",
        justifyContent:"center",
        alignItems:"center"
    })
    
}
// 设置样式的方法
Page.prototype.setStyle = function(ele,styleObj){
    for(var attr in styleObj){
        ele.style[attr] = styleObj[attr]
    }
}
// new构造函数并传入需要的实参
var page = new Page(".pagination",{
    language:{
        first:"首页",
        prev:"上一页",
        next:"下一页",
        last:"尾页"
    },
    pageData:{
        total:100,
        pageSize:10
    }
})

代码逻辑分析:

参数是可选项,所以要对参数做默认值

function Page(classname,options={}){ // 给options设置默认值
     this.box = document.createElement('div') // 自己创建一个div容器
    // 将创建好的div容器放到预定好的盒子中
    document.querySelector('.' + classname).appendChild(this.box) 
    // 给创建好的div设置样式
    this.setStyle(this.box,{
        display:"flex",
        justifyContent:"center",
        alignItems:"center"
    })
    // 将传入的options参数作为对象的options属性
    this.options = options
    // 自定义默认值
    this.default = {
        language:{
            first:"首",
            prev:"上",
            next:"下",
            last:"尾"
        },
        pageData:{
            total:1000,
            pageSize:12
        }
    }
    // 调用设置默认值的方法
    this.setDefault()
}
// 设置默认值的方法
Page.prototype.setDefault = function(){
    // 如果传入的options中传了language键
    if(this.options.language){
        for(var attr in this.options.language){
            // 使用options传入的值替换掉自定义的默认值
            this.default.language[attr] = this.options.language[attr]
        }
    }
    if(this.options.pageData){
        for(var attr in this.options.pageData){
            this.default.pageData[attr] = this.options.pageData[attr]
        }
    }
}

此时参数就成了可选项

有了参数后,可以计算总页数,定义当前页,....

创建div标签

Page.prototype.createDiv = function(){
    for(var attr in this.default.language){
        var div = document.createElement('div')
        div.innerText = this.default.language[attr];
        div.className = attr
        this.setStyle(div,{
            margin:"5px",
            padding:"5px",
            border:"1px solid #000"
        })
        this.box.appendChild(div)
    }
}

创建好的标签少了中间放页码的div,所以要在自定义的默认值中,加一个list,用来存放这div

this.default = {
    language:{
        first:"首",
        prev:"上",
        list:'',
        next:"下",
        last:"尾"
    },
    pageData:{
        total:1000,
        pageSize:12
    }
}

对创建标签的方法进行修改 - 因为放页码的盒子要又不同的样式以及在别的方法中会用到这div,所以将div赋值给一个自定义的属性:

对象新增属性

this.setDefault()
// 总页数属性
this.totalPage = Math.ceil(this.default.pageData.total/this.default.pageData.pageSize)
// 当前页属性 - 当前页默认为1
this.currentPage = 1
// 设置放页码盒子的属性
this.list = null

创建页码的方法修改:

Page.prototype.createDiv = function(){
    for(var attr in this.default.language){
        var div = document.createElement('div')
        if(attr=='list'){ // 如果是list,就将div赋值给自定义的属性list
            this.list = div
        }else{
            // 其余div都设置内容和样式
            div.innerText = this.default.language[attr];
            this.setStyle(div,{
                margin:"5px",
                padding:"5px",
                border:"1px solid #000"
            })
        }
        div.className = attr // 给每个div添加类名
        this.box.appendChild(div) // 将创建好的div放到自己创建好的容器中
    }
}

创建页码

Page.prototype.createPage = function(){
    if(this.totalPage<=5){
        for(var i=1;i<=this.totalPage;i++){
            var p = document.createElement('p')
            p.innerText = i
            if(i==this.currentPage){
                p.style.background = 'orange';
            }
            this.setStyle(p,{
                margin:"5px",
                padding:'5px',
                border:"1px solid #000"
            })
            this.list.appendChild(p)
        }
    }else{
        if(this.currentPage<=3){
            for(var i=1;i<=5;i++){
                var p = document.createElement('p')
                p.innerText = i
                if(i==this.currentPage){
                    p.style.background = 'orange';
                }
                this.setStyle(p,{
                    margin:"5px",
                    padding:'5px',
                    border:"1px solid #000"
                })
                this.list.appendChild(p)
            }
        }else if(this.currentPage>=this.totalPage-2){
            for(var i=this.totalPage-4;i<=this.totalPage;i++){
                var p = document.createElement('p')
                p.innerText = i
                if(i==this.currentPage){
                    p.style.background = 'orange';
                }
                this.setStyle(p,{
                    margin:"5px",
                    padding:'5px',
                    border:"1px solid #000"
                })
                this.list.appendChild(p)
            }
        }else{
            for(var i=this.currentPage-2;i<=this.currentPage+2;i++){
                var p = document.createElement('p')
                p.innerText = i
                if(i==this.currentPage){
                    p.style.background = 'orange';
                }
                this.setStyle(p,{
                    margin:"5px",
                    padding:'5px',
                    border:"1px solid #000"
                })
                this.list.appendChild(p)
            }
        }
    }
}

此时页码显示的样式不能同行显示,所以要在创建好中间的类名叫listdiv的时候,就应该给他设置好样式:

this.list = div
this.setStyle(div,{
    display:"flex",
    justifyContent:"center",
    alignItems:"center"
})

创建文本框和跳转按钮

Page.prototype.createGo = function(){
    var input = document.createElement('input')
    input.setAttribute('type','number')
    this.setStyle(input,{
        width:'44px',
        height:'29px',
        border:'none',
        border:'1px solid #000',
        outline:"none",
        paddingLeft:'6px',
        margin:"5px"
    })
    this.box.appendChild(input)
    var btn = document.createElement('button')
    btn.innerText = 'GO';
    this.setStyle(btn,{
        width:'50px',
        border:'none',
        border:'1px solid #000',
        outline:'none',
        height:'33px',
        margin:'5px',
        background:'#abcdef'
    })
    this.box.appendChild(btn)
}

点击标签让页码动起来

因为点击的所有子标签都在大盒子中,所以使用事件委托来实现

Page.prototype.clickTag = function(){
    this.box.onclick = e=>{
        var e = e || window.event;
        var target = e.target || e.srcElement;
        if(target.className === 'first' && target.getAttribute('disabled') !== 'true'){
            this.currentPage = 1
            this.list.innerHTML = '';   
            this.createPage()
            this.clickTag()
            this.setDisabled()
        }else if(target.className === 'last' && target.getAttribute('disabled') !== 'true'){
            this.currentPage = this.totalPage-0
            this.list.innerHTML = '';   
            this.createPage()
            this.clickTag() 
            this.setDisabled()
        }else if(target.className === 'prev' && target.getAttribute('disabled') !== 'true'){
            this.currentPage--
            this.list.innerHTML = '';   
            this.createPage()
            this.clickTag() 
            this.setDisabled()
        }else if(target.className === 'next' && target.getAttribute('disabled') !== 'true'){
            this.currentPage++
            this.list.innerHTML = '';   
            this.createPage()
            this.clickTag() 
            this.setDisabled()
        }else if(target.nodeName === 'P' && target.innerText-0   !== this.currentPage){
            this.currentPage = target.innerText - 0
            this.list.innerHTML = '';   
            this.createPage()
            this.clickTag() 
            this.setDisabled()
        }else if(target.nodeName === 'BUTTON' && target.previousElementSibling.value-0 !== this.currentPage){
            if(target.previousElementSibling.value-0>this.totalPage){
                target.previousElementSibling.value = this.totalPage
            }
            if(target.previousElementSibling.value-0<1){
                target.previousElementSibling.value = 1
            }
            this.currentPage = target.previousElementSibling.value - 0
            this.list.innerHTML = '';   
            this.createPage()
            this.clickTag() 
            this.setDisabled()
            this.show(this.currentPage)
        }
    }
}

在首页的时候不能点击上一页和首页,所以,要设置禁用项,并在每次点击之后,重新加载完页码后要调用禁用项

设置禁用项

Page.prototype.setDisabled = function(){
    if(this.currentPage === 1){
        this.box.children[0].setAttribute('disabled',true)
        this.box.children[1].setAttribute('disabled',true)
        this.box.children[0].style.backgroundColor = this.box.children[1].style.backgroundColor = 'gray'
    }else{
        this.box.children[0].setAttribute('disabled',false)
        this.box.children[1].setAttribute('disabled',false)
        this.box.children[0].style.backgroundColor = this.box.children[1].style.backgroundColor = 'transparent'
    }
    if(this.currentPage === this.totalPage){
        this.box.children[3].setAttribute('disabled',true)
        this.box.children[4].setAttribute('disabled',true)
        this.box.children[3].style.backgroundColor = this.box.children[4].style.backgroundColor = 'gray'
    }else{
        this.box.children[3].setAttribute('disabled',false)
        this.box.children[4].setAttribute('disabled',false)
        this.box.children[3].style.backgroundColor = this.box.children[4].style.backgroundColor = 'transparent'
    }
}

至此,分页插件已经制作完成,需要设置如何使用这个插件

使用插件

数据:

// 生成1000条数据
var firstnameArr = ['赵','钱','孙','李','周','吴','郑','王','冯','陈','褚','卫','蒋','沈','韩','杨']
var secondnameArr = ['甲','乙','丙','丁','戊','己','庚','辛','壬','癸'];
var thirdnameArr = ['子','丑','寅','卯','辰','巳','午','未','申','酉','戌','亥']
var arr = []
for(var i=0;i<1000;i++){
    var firstIndex = Math.floor(Math.random()*firstnameArr.length)
    var secondIndex = Math.floor(Math.random()*secondnameArr.length)
    var thirdIndex = Math.floor(Math.random()*thirdnameArr.length)
    var obj = {
        name:firstnameArr[firstIndex] + secondnameArr[secondIndex] + thirdnameArr[thirdIndex],
        age:Math.floor(Math.random()*100),
        sex:['男','女'][Math.floor(Math.random()*2)]
    }
    arr.push(obj)
}

数据需要通过插件来加载,每页展示的数据需要进行截取后展示在页面中,截取数据的规律如下:截取后的数据 = 数组.slice((当前页-1)*每页展示的条数,当前页*每页展示的条数)

在这公式中,每页展示的条数,是自己决定的,但是当前页需要在插件中才能知道,所以,给插件传入一个函数,让插件来调用这个函数,并将插件中的当前页当做形参传入这个函数,函数中就能使用当前页了

调用时传入一个函数

var pageSize = 10
var page = new Page("pagination",{
    language:{
        first:"首页",
        prev:"上一页",
        next:"下一页",
        last:"尾页"
    },
    pageData:{
        total:arr.length,
        pageSize
    },
    show:function(currentPage){
        document.querySelector('tbody').innerHTML = ''  
        var res = arr.slice((currentPage-1)*pageSize,currentPage*pageSize)
        console.log(res)
        for(var i=0;i<res.length;i++){
            var tr = document.createElement('tr')
            if(i%2===0){
                tr.bgColor = 'pink'
            }else{
                tr.bgColor = 'skyblue';
            }
            for(var attr in res[i]){
                var td = document.createElement('td')
                td.innerText = res[i][attr]
                tr.appendChild(td)
            }
            var td = document.createElement('td')
            td.innerText = '删除'
            tr.appendChild(td)
            document.querySelector('tbody').appendChild(tr)
        }
    }
})

构造函数中处理这个函数

this.default = {
        language:{
            first:"首",
            prev:"上",
            list:'',
            next:"下",
            last:"尾"
        },
        pageData:{
            total:1000,
            pageSize:12
        },
        show:this.options.show || function(){}
    }

在每次有了页码后就调用这个函数

this.createDiv()
this.createPage()
this.clickTag()
this.setDisabled()
this.show(this.currentPage)

代码整理

构造函数

function Page(classname,options={}){
    // 创建放分页的大盒子
    this.box = document.createElement('div')
    // 给创建后的大盒子设置样式
    this.setStyle(this.box,{
        display:"flex",
        justifyContent:"center",
        alignItems:"center"
    })
    // 将创建好的大盒子放到在页面中预备好放分页的盒子
    document.querySelector('.' + classname).appendChild(this.box)
    // 将传入的options参数作为对象的属性
    this.options = options
    // 定义default属性作为将来要使用的配置参数
    this.default = {
        language:{
            first:"首",
            prev:"上",
            list:'',
            next:"下",
            last:"尾"
        },
        pageData:{
            total:1000,
            pageSize:12
        },
    }
    // 使用分页插件的show方法作为对象的方法并设置默认值
    this.show = this.options.show || function(){}
    // 调用方法设置参数尾可选项
    this.setDefault()
    // 总页数属性
    this.totalPage = Math.ceil(this.default.pageData.total/this.default.pageData.pageSize)
    // 当前页属性 - 当前页默认为1
    this.currentPage = 1
    // 设置放页码盒子的属性
    this.list = null
    // 创建分页中的几个div - 首页、上一页、放页码的div、下一页、尾页
    this.createDiv()
    // 创建文本框和按钮
    this.createGo()
    // 调用初始化方法 - 创建页码、点击翻页、设置禁用项、调用传入的使用插件的方法
    this.init()
}

初始化方法

// 初始化方法
Page.prototype.init = function(){
    // 创建页码
    this.createPage()
    // 点击翻页
    this.clickTag()
    // 设置禁用项
    this.setDisabled()
    // 调用使用插件的方法
    this.show(this.currentPage)
}

创建文本框和按钮

// 创建文本框和按钮
Page.prototype.createGo = function(){
    // 创建input标签
    var input = document.createElement('input')
    // 设置input的type属性
    input.setAttribute('type','number')
    // 给input设置样式
    this.setStyle(input,{
        width:'44px',
        height:'29px',
        border:'none',
        border:'1px solid #000',
        outline:"none",
        paddingLeft:'6px',
        margin:"5px"
    })
    // 将input标签放在大盒子中
    this.box.appendChild(input)
    // 创建按钮
    var btn = document.createElement('button')
    // 给按钮中放内容
    btn.innerText = 'GO';
    // 给按钮设置样式
    this.setStyle(btn,{
        width:'50px',
        border:'none',
        border:'1px solid #000',
        outline:'none',
        height:'33px',
        margin:'5px',
        background:'#abcdef'
    })
    // 将按钮放如大盒子
    this.box.appendChild(btn)
}

设置禁用项

// 设置禁用项
Page.prototype.setDisabled = function(){
    // 如果当前是第一页
    if(this.currentPage === 1){
        // 给首页和上一页设置disabled属性,值为true
        this.box.children[0].setAttribute('disabled',true)
        this.box.children[1].setAttribute('disabled',true)
        // 将首页和上一页的背景设置为灰色
        this.box.children[0].style.backgroundColor = this.box.children[1].style.backgroundColor = 'gray'
    }else{ // 如果当前不是第一页
        // 给首页和上一页设置disabled属性,值尾false
        this.box.children[0].setAttribute('disabled',false)
        this.box.children[1].setAttribute('disabled',false)
        // 将首页和上一页的背景设置为透明
        this.box.children[0].style.backgroundColor = this.box.children[1].style.backgroundColor = 'transparent'
    }
    // 如果当前是最后一页
    if(this.currentPage === this.totalPage){
        // 给下一页和尾页设置disabled属性,值为true
        this.box.children[3].setAttribute('disabled',true)
        this.box.children[4].setAttribute('disabled',true)
        // 将下一页和尾页的背景设置为灰色
        this.box.children[3].style.backgroundColor = this.box.children[4].style.backgroundColor = 'gray'
    }else{ // 如果当前不是最后一页
        // 给下一页和尾页设置disabled属性,值为false
        this.box.children[3].setAttribute('disabled',false)
        this.box.children[4].setAttribute('disabled',false)
        // 将下一页和尾页的背景设置为透明
        this.box.children[3].style.backgroundColor = this.box.children[4].style.backgroundColor = 'transparent'
    }
}

点击翻页

// 点击标签翻页 - 使用事件委托
Page.prototype.clickTag = function(){
    // 给大盒子绑定单击事件 - 为了能在事件函数中使用的this是外面new的对象,所以使用箭头函数
    this.box.onclick = e=>{
        // 获取事件对象
        var e = e || window.event;
        // 通过事件对象获取目标元素
        var target = e.target || e.srcElement;
        // 如果目标元素是首页,且disabled属性不是true
        if(target.className === 'first' && target.getAttribute('disabled') !== 'true'){
            // 将当前页设置为1
            this.currentPage = 1
            // 调用初始化方法
            this.init()
        // 如果目标元素是尾页,且disabled属性不是true
        }else if(target.className === 'last' && target.getAttribute('disabled') !== 'true'){
            // 将当前页设置为最后一页
            this.currentPage = this.totalPage-0
            // 调用初始化方法
            this.init()
        // 如果目标元素是上一页,且disabled属性不是true
        }else if(target.className === 'prev' && target.getAttribute('disabled') !== 'true'){
            // 让当前页自减
            this.currentPage--
            // 限制最小的当前页
            if(this.currentPage<=1){
               this.currentPage = 1
            }
            // 调用初始化方法
            this.init()
        // 如果目标元素是下一页,且disabled属性不是true
        }else if(target.className === 'next' && target.getAttribute('disabled') !== 'true'){
            // 让当前页自增
            this.currentPage++
            // 限制最大的当前页
            if(this.currentPage>=this.totalPage){
               this.currentPage = this.totalPage
            }
            // 调用初始化方法
            this.init()
        // 如果目标元素是页码标签p标签且这个页码标签中的数字不是当前页
        }else if(target.nodeName === 'P' && target.innerText-0 !== this.currentPage){
            // 将当前页设置为当前点击的页码标签中的数字
            this.currentPage = target.innerText - 0
            // 调用初始化方法
            this.init()
        // 如果目标元素是按钮且按钮前面的input中输入的数字不是当前页
        }else if(target.nodeName === 'BUTTON' && target.previousElementSibling.value-0 !== this.currentPage){
            // 如果文本框中的数字大于总页数
            if(target.previousElementSibling.value-0>this.totalPage){
                // 将输入框中的数字设置为总页数
                target.previousElementSibling.value = this.totalPage
            }
            // 如果文本框中的数字小于1
            if(target.previousElementSibling.value-0<1){
                // 将输入框中的数字设置为1
                target.previousElementSibling.value = 1
            }
            // 将当前页设置为按钮前面的文本框中输入的数字
            this.currentPage = target.previousElementSibling.value - 0
            // 调用初始化方法
            this.init()
        }
    }
}

创建页码

// 创建页码
Page.prototype.createPage = function(){
    // 将放页码的div中的内容清空
    this.list.innerHTML = '';   
    // 如果总页数不大于5
    if(this.totalPage<=5){
        // 循环创建1~总页数的页码
        for(var i=1;i<=this.totalPage;i++){
            // 创建p标签
            var p = document.createElement('p')
            // 将页码放在p标签中
            p.innerText = i
            // 如果是当前页
            if(i==this.currentPage){
                // 将放当前页的p标签设置为橘色
                p.style.background = 'orange';
            }
            // 给所有p标签设置样式
            this.setStyle(p,{
                margin:"5px",
                padding:'5px',
                border:"1px solid #000"
            })
            // 将创建好的每一个p标签放在list页码div中
            this.list.appendChild(p)
        }
    }else{ // 如果当前页大于5
        if(this.currentPage<=3){ // 如果当前页小于等于3 - 展示页码为1~5
            // 循环前5个页码数字
            for(var i=1;i<=5;i++){
                // 创建p标签
                var p = document.createElement('p')
                // 将页码放在p标签中
                p.innerText = i
                // 如果是当前页
                if(i==this.currentPage){
                    // 将放当前页的p标签设置为橘色
                    p.style.background = 'orange';
                }
                // 给所有p标签设置样式
                this.setStyle(p,{
                    margin:"5px",
                    padding:'5px',
                    border:"1px solid #000"
                })
                // 将创建好的每一个p标签放在list页码div中
                this.list.appendChild(p)
            }
        }else if(this.currentPage>=this.totalPage-2){ // 如果当前页是最后3页 - 展示页码为最后5页
            // 循环最后5个页码数字
            for(var i=this.totalPage-4;i<=this.totalPage;i++){
                // 创建p标签
                var p = document.createElement('p')
                // 将页码放在p标签中
                p.innerText = i
                // 如果是当前页
                if(i==this.currentPage){
                    // 将放当前页的p标签设置为橘色
                    p.style.background = 'orange';
                }
                // 给所有p标签设置样式
                this.setStyle(p,{
                    margin:"5px",
                    padding:'5px',
                    border:"1px solid #000"
                })
                // 将创建好的每一个p标签放在list页码div中
                this.list.appendChild(p)
            }
        }else{ // 当前页是中间的页码,展示页码为当前页-2~当前页+2
            // 循环当前页-2~当前页+2这5个页码数字
            for(var i=this.currentPage-2;i<=this.currentPage+2;i++){
                // 创建p标签
                var p = document.createElement('p')
                // 将页码放在p标签中
                p.innerText = i
                // 如果是当前页
                if(i==this.currentPage){
                    // 将放当前页的p标签设置为橘色
                    p.style.background = 'orange';
                }
                // 给所有p标签设置样式
                this.setStyle(p,{
                    margin:"5px",
                    padding:'5px',
                    border:"1px solid #000"
                })
                // 将创建好的每一个p标签放在list页码div中
                this.list.appendChild(p)
            }
        }
    }
}

创建div

// 创建首页、上一页、放页码的div、下一页、尾页
Page.prototype.createDiv = function(){
    // 遍历设置好的配置参数
    for(var attr in this.default.language){
        // 创建div标签
        var div = document.createElement('div')
        // 如果是放页码的盒子 - 不放内容
        if(attr=='list'){
            this.list = div // 将div赋值给设置好的list属性
            // 给放页码的div设置样式
            this.setStyle(div,{
                display:"flex",
                justifyContent:"center",
                alignItems:"center"
            })
        }else{ // 如果不是放页码的div
            // 给div中放入配置好的内容
            div.innerText = this.default.language[attr];
            // 给div设置样式
            this.setStyle(div,{
                margin:"5px",
                padding:"5px",
                border:"1px solid #000"
            })
        }
        // 给创建好div设置类名
        div.className = attr
        // 将创建好的div放如大盒子中
        this.box.appendChild(div)
    }
}

设置配置参数

// 设置配置参数
Page.prototype.setDefault = function(){
    // 如果传入的options中有language键
    if(this.options.language){
        // 遍历传入的language,代替默认的language
        for(var attr in this.options.language){
            this.default.language[attr] = this.options.language[attr]
        }
    }
    // 如果传入的options中有pageData键
    if(this.options.pageData){
        // 遍历传入的pageData,代替默认的pageData
        for(var attr in this.options.pageData){
            this.default.pageData[attr] = this.options.pageData[attr]
        }
    }
}

设置样式的方法

// 设置样式的方法
Page.prototype.setStyle = function(ele,styleObj){
    for(var attr in styleObj){
        ele.style[attr] = styleObj[attr]
    }
}

最终效果

使用分页插件的效果

举报

相关推荐

0 条评论