用vue寫輪子的一些心得(八)——pager分頁器組件

需求分析

  • 支持傳入當前頁碼參數並展示;
  • 支持頁數過多的部分用省略號顯示,並會動態變化;
  • 支持支持點擊左右方向鍵切換頁碼;
  • 支持在只有一頁的時候隱藏pager;

 

方法實現

1、pager外部組件傳參定義:

一共可傳4個參數:

  • total,頁碼條數
  • current,當前頁碼
  • current.sync,點擊頁碼的current參數回調
  • hide-one-page, 默認不填一頁時顯示,false則隱藏
<T-pager :total="10" :current="1" :current.sync="currentPage" :hide-one-page="false"></T-pager>

2、pager組件內部實現:

HTML

<template>
    <div class="pager-content" :class="{hide: !hideOnePage && pages <= 1}">
        <span class="pager-content-nav prev"
              @click="onClickPage(current-1)"
              :class="{disabled: current === 1}">
            <t-icon name="left"></t-icon>
        </span>
        <template v-for="page in pages">
            <template v-if="page === current">
                <span class="pager-content-item current">{{page}}</span>
            </template>
            <template v-else-if="page === '...'">
                <span class="pager-content-item separator">...</span>
            </template>
            <template v-else>
                <span class="pager-content-item other" @click="onClickPage(page)">{{page}}</span>
            </template>
        </template>
        <span class="pager-content-nav next"
              @click="onClickPage(current+1)"
              :class="{disabled: current === total}">
            <t-icon name="right"></t-icon>
        </span>
    </div>
</template>

JS

<script>
    import TIcon from '../icon'

    export default {
        name: 'pager',

        components: {
            TIcon
        },

        props: {
            total: {
                type: Number,
                default: 1
            },
            current: {
                type: Number,
                default: 1
            },
            hideOnePage: {
                type: Boolean,
                default: true
            }
        },

        computed: {
            pages() {
                let pages = [1, this.total, this.current, this.current-1, this.current-2, this.current+1, this.current+2]
                let u = pages.filter(n => n >= 1 && n <= this.total)
                let u1 = this.unique(u.sort((a, b) => a - b))
                return u1.reduce((a, b, index, array) => { // 過濾,添加...
                    a.push(b)
                    if (array[index + 1] !== undefined && array[index+1] - array[index] > 1) {
                        a.push('...')
                    }
                    return a
                }, [])
            }
        },

        methods: {
            onClickPage(n) {
                if (n >=1 && n <= this.total) {
                    this.$emit('update:current', n)
                }
            },
            unique(array) { //數組去重
                const object = {}
                array.map(item => {
                    object[item] = true
                })
                return Object.keys(object).map(value => parseInt(value, 10))
            }
        }
    }
</script>
  1. 省略號:通過計算屬性pages,四重遍歷動態計算出省略號的位置,小於5條total則不展示省略號。
  2. 監聽pager點擊結構樣式變化:onClickPage()方法,將變化的數據傳出去,再通過current.sync接收,更新current的值,從而達到單向數據流的目的,實現功能的同時,還可簡化邏輯。
  3. 一頁樣式隱藏:通過css類做判斷即可。
  4. 左右方向箭頭切換:增加或減少current的值即可,但要留意邊界情況(小於1條大於最後一條),最後走‘update:current’單向數據流出發外部current參數回調即可。

 

3、在v-for中使用不同標籤展示數據的方法:

參考下面的HTML代碼,只需通過template模板遍歷即可。應爲template模板標籤在瀏覽器渲染中不會變成標籤。

<template v-for="page in pages">
    <template v-if="page === current">
        <span class="pager-content-item current">{{page}}</span>
    </template>
    <template v-else-if="page === '...'">
        <div class="pager-content-item separator">...</div>
    </template>
    <template v-else>
        <a class="pager-content-item other" @click="onClickPage(page)">{{page}}</a>
    </template>
</template>

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章