從零實現Vue的元件庫(十三)- Pagination 實現

Yzz發表於2019-02-01

當資料量過多時,使用分頁分解資料

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. 結論

分頁器的具體邏輯一般都是與互動的設計相關,上述方法將其原理拆分的很清晰,按照具體需求修改一些引數就可以。

往期文章:

原創宣告: 該文章為原創文章,轉載請註明出處。

相關文章