徒手撸UI之Paginator

QingUI是一个UI组件库

如今具有的组件:DatePicker, TimePicker, Paginator, Tree, Cascader, Checkbox, Radio, Switch, InputNumber, Input

ES6语法编写,无依靠

原生模块化,Chrome63以上支撑,请开启静态服务器预览结果,
静态服务器传送门

采纳CSS变量设置款式

辛劳造轮子,欢迎来github堆栈star:
https://github.com/veedrin/qing

四月份找事情,求内推,坐标深圳

写在前面

客岁岁尾项目中尝试着写过一个分页的Angular组件,然后就有了写QingUI的主意

历程照样异常有意义的

接下来我会用几篇文章离别引见每一个组件的也许思绪,请人人耐烦守候

这一篇引见Paginator分页

最主要的,求star,求fork,求内推

repo:
QingUI

少废话,先上图

《徒手撸UI之Paginator》

为何要有分页

平常的需求是,我有一个列表,然则我不想一下让用户看这么多,一次看一点,再想看,翻到下一页

固然如今有无限转动,只需转动到肯定间隔,就给你加载新的数据,这个我们不斟酌

分页也有两种做法,一种是一次性加载一切数据,前端做分页;一种是每次加载一部分,点击分页就是触发再次加载的行动

第一种做法应当很少见了吧,初次加载的压力太大

分页怎样事情

页面初始加载的时刻向背景要求数据,要求哪些数据呢?要显现的列表信息,另有当前是第几页

如果每页显现若干条是可设置的,那末还须要每页显现若干条和总条数

初始加载肯定是第一页

然后用户看完第一页,往下翻,多是翻到第二页,也多是翻到背面的任一页,无所谓

我们获取到用户想翻到第几页的信息今后,传给后端,后端再把响应页的列表信息传过来,前端展现

注重,这个时刻分页是要变的,用户点击的那一页要高亮,之前那一页去掉高亮,如果页数比较多,省略号的位置也要依据划定规矩发生变化

所以我们得出一个主要信息,分页组件展现页码的那一块每次点击都是要从新衬着的

$bar就是展现页码的容器,展现页码的模板封装到另一个函数里

一最先能想到这个,背面就不须要推倒重来了,你猜我有无推倒重来 :)

tpl += `
    <div class="square end prev">﹤</div>
    <div class="bar"></div>
    <div class="square end next">﹥</div>
`;

数据模型

如果我们把展现逻辑放到模板衬着函数里,那模板衬着函数会变得异常冗杂

我们能够分红两步,第一步构建数据模型,第二步依据数据模型天生模板

我细致的视察过GitHub(GitHub已异常优美了)的分页逻辑,QingUI的分页逻辑就是依据GitHub来的

我总结了一下,代码诠释里也有:

  • 首页和尾页必需展现
  • 如果有省略号则首尾只展现一条,当前页前后各展现两条共五条,一边没有空间则叠加到另一边
  • 首尾页与当前页五条能够重合
  • 跨度大于即是两条才涌现省略号,省略号用0示意

哦,忘了诠释,数据模型是怎样映照的

分页都是从1最先,最大随便(平常不会太大),所以我们构建一个数组,1到正无限就代表1到正无限页,0代表省略号

总页数在1到7页之间

1到7页之间能够完整展现,为何?

首尾各1页,中心共5页,加起来就是7页,凌驾7页就会有省略号

不是说跨度大于即是2页才会有省略号吗?

由于首页和中心的5页是能够重合的,如果有8页,前面5页和末了1页中心恰好隔了2页

所以1到7页之间能够完整展现

for (let i = 1; i <= c; i++) {
    this.model.push(i);
}

总页数7页以上且当前页小于4

如果当前页小于4,最少要保证当前页加摆布最少有5页,所以这类状况要零丁拎出来

背面再加一个省略号,以及尾页

for (let i = 1; i <= 5; i++) {
    this.model.push(i);
}
this.model.push(0, c);

总页数7页以上且当前页小于6

这类状况就是首页和中心5页不重合的状况,所以for轮回不须要写死

一样,背面再加一个省略号,以及尾页

for (let i = 1; i <= p + 2; i++) {
    this.model.push(i);
}
this.model.push(0, c);

总页数7页以上且当前页小于总页数减4

这类状况就是间隔首页的跨度大于即是2,间隔尾页的跨度也大于即是2,因而前后都有省略号

this.model.push(1, 0);
for (let i = p - 2; i <= p + 2; i++) {
    this.model.push(i);
}
this.model.push(0, c);

总页数7页以上且当前页小于总页数减1

这类状况是说背面没有省略号了,然则也不至于和尾页发生重合

this.model.push(1, 0);
for (let i = p - 2; i <= c; i++) {
    this.model.push(i);
}

总页数7页以上且当前页即是总页数减1或许即是总页数

中心5页与尾页发生重合了,最少要保证衬着出5页,所以for轮回写死

this.model.push(1, 0);
for (let i = c - 4; i <= c; i++) {
    this.model.push(i);
}

总结

6种状况:

  • 没有省略号
  • 前面有省略号然则中心5页与首页重合
  • 前面有省略号且中心5页与首页不重合
  • 前面和背面都有省略号
  • 背面有省略号且中心5页与尾页不重合
  • 背面有省略号然则中心5页与尾页重合

照样挺有规律的是吧

数据模型代码

buildModel() {
    // 每次从新初始化
    this.model = [];
    const c = this.pageCount, p = this.position;
    if (c < 8) {
        for (let i = 1; i <= c; i++) {
            this.model.push(i);
        }
    } else {
        if (p < 4) {
            for (let i = 1; i <= 5; i++) {
                this.model.push(i);
            }
            this.model.push(0, c);
        } else if (p < 6) {
            for (let i = 1; i <= p + 2; i++) {
                this.model.push(i);
            }
            this.model.push(0, c);
        } else {
            if (p < c - 4) {
                this.model.push(1, 0);
                for (let i = p - 2; i <= p + 2; i++) {
                    this.model.push(i);
                }
                this.model.push(0, c);
            } else if (p < c - 1) {
                this.model.push(1, 0);
                for (let i = p - 2; i <= c; i++) {
                    this.model.push(i);
                }
            } else {
                this.model.push(1, 0);
                for (let i = c - 4; i <= c; i++) {
                    this.model.push(i);
                }
            }
        }
    }
}

如果你不喜欢GitHub分页划定规矩,或许本身有特别的需求

能够依据上面的规律本身定制一套分页逻辑

真的,往上套就能够了

衬着

数据模型都构建出来了,衬着就简朴了

for (const item of this.model) {
    if (item > 0) {
        if (this.position !== item) {
            tpl += `<div class="square page">${item}</div>`;
        } else {
            tpl += `<div class="square page active">${item}</div>`;
        }
    } else {
        tpl += '<div class="square gap">···</div>';
    }
}

prev和next置灰

在某些状况,我们要让用户晓得往前或许今后点击是无效的,要举行置灰处置惩罚

划定规矩也挺简朴的

如果当前页是第1页

if (this.position === 1) {
    this.$prev.classList.add('disabled');
    this.$next.classList.remove('disabled');
}

如果当前页是末了1页

if (this.position === this.pageCount) {
    this.$next.classList.add('disabled');
    this.$prev.classList.remove('disabled');
}

如果当前页既不是第1页也不是末了1页

if (this.position === this.pageCount) {
    this.$prev.classList.remove('disabled');
    this.$next.classList.remove('disabled');
}

如果总页数是1

这类状况很轻易被疏忽

如果统共只要1页,那摆布都点不了,而且马上返回

if (this.pageCount === 1) {
    this.$prev.classList.add('disabled');
    this.$next.classList.add('disabled');
    return;
}

能够设置每页显现若干条

这里主如果注重一个题目

如果如今的当前页是比较靠后的位置

然后我增添每页显现的条数,那必将总页数就变小了

有能够总页数变的比当前页还小

那末这个时刻就只能强迫转变当前页,让它变成末了1页了

能够自在跳转

这就是一个输入框,加keyup监听Enter键的事宜

写在背面

Paginator比较中心的逻辑就在这里了

最有意义的是构建数据模型的那一段,挺费头脑的

下一篇文章引见Tree,敬请期待

末了,求star,求fork,求内推

repo:
QingUI

    原文作者:JsTheGreat
    原文地址: https://segmentfault.com/a/1190000013973011
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞