从零实现Vue的组件库(十三)- Pagination 实现
阅读原文时间:2021年04月20日阅读:1

当数据量过多时,使用分页分解数据

Pagination 组件主要特点在于:

  • 利用 v-model 方便拓展;
  • 利用 computed 完成内部逻辑解析。

1. 实例

代码

<fat-pagination
    :total="1000"
    :page-size="20"
    :page-count="11"
    @change="handleChange"
/>
复制代码

实例地址:Pagination 实例

代码地址:Github UI-Library

2. 原理

基本结构非常简单,可以分为前 forwardPaginations 、中 middlePaginations、后 backwardPaginations,三个部分

<div class="pagination-wrapper">
    <ul :class="['pagination-inner', { 'has-background': background }]">
        <!-- backward Paginations -->
        <li
            v-for="item in forwardPaginations"
            :key="item"
            :class="['pagination-item', { 'is-active': item === current }]"
            @click.stop="handleClick({ type: 'select', data: item })"
        >{{ item }}</li>
      <!-- end -->
      <!-- middle paginations -->
      <template v-if="isForwardBrief && isBackwardBrief">
        <li
            v-for="item in middlePaginations"
            :key="item"
            :class="['pagination-item', { 'is-active': item === current }]"
            @click.stop="handleClick({ type: 'select', data: item })"
        >{{ item }}</li>
      </template>
      <!-- end -->
      <!-- backward paginations -->
      <li
            v-for="item in backwardPaginations"
            :key="item"
            :class="['pagination-item', { 'is-active': item === current }]"
            @click.stop="handleClick({ type: 'select', data: item })"
      >{{ item }}</li>
      <!-- end -->
    </ul>
</div>
复制代码

forwardPaginations :前向的 Pagination 主要包含两种状态,缩略或者是展开,当 current 的值超出所设定的红框范围时候,就会呈现缩略状。

也就是依据 paginalNumber > pageCount && current > pageCount - 3 进行判断

data() {
    return {
        current: 1
    };
},
computed: {
    // 页数
    paginalNumber() {
        const { total, pageSize } = this;
        return Math.ceil(total / pageSize);
    },
    // 前向是否缩略
    isForwardBrief() {
        const { paginalNumber, pageCount, current } = this;
        return paginalNumber > pageCount && current > pageCount - 3;
    }
  }
复制代码

具体的展示的页码 forwardPaginations

forwardPaginations() {
    const { pageCount, isForwardBrief, paginalNumber } = this;
    let start = 0;
    let length = paginalNumber <= pageCount
        ? paginalNumber
        : isForwardBrief
        ? 1
        : pageCount;

    return Array.from({ length }, (v, i) => {
        return i + start + 1;
    });
}
复制代码

同样的原理,还有后向页码 backwardPaginations

isBackwardBrief() {
    const { paginalNumber, pageCount, current } = this;
    return paginalNumber > pageCount && current < paginalNumber - 3;
},
backwardPaginations() {
    const { current, pageCount, isBackwardBrief, paginalNumber } = this;
    let start = paginalNumber - (isBackwardBrief ? 1 : pageCount + 1);
    let length = paginalNumber <= pageCount ? 0 : isBackwardBrief ? 1 : pageCount + 1;

    return Array.from({ length }, (v, i) => {
        return i + start + 1;
    });
}
复制代码

当上述的 computed 属性,满足 isBackwardBrief && isForwardBrief 的条件时候,说明当前前后都处于缩略状态,这是需要生成中间的页码

生成的规则就是以 current 为中心,左右拓展 offset 个页码。

middlePaginations() {
    const { current, pageCount, isForwardBrief, isBackwardBrief } = this;
    const offset = Math.round(pageCount / 2);
    let start = current - offset;

    return Array.from({ length: pageCount }, (v, i) => {
        return i + start + 1;
    });
}
复制代码

处理 v-model

model: {
    prop: "value",
    event: "change"
}
复制代码

为什么要实现数据的双向绑定,是因为经常有需要实现图中需求

这样可以,通过修改 v-model 所绑定的值进行二次封装。

3. 结论

分页器的具体逻辑一般都是与交互的设计相关,上述方法将其原理拆分的很清晰,按照具体需求修改一些参数就可以。

往期文章:

原创声明: 该文章为原创文章,转载请注明出处。

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器

你可能感兴趣的文章