vue技術帖-實現一款簡單通用的翻頁組件

預覽

先上一波效果圖:javascript

clipboard.png

基本元素

首先,翻頁組件(如下稱「pager組件」)通常擁有的元素有:html

  • 上一頁vue

  • 第一頁java

  • 中間顯示的頁碼git

  • 最後一頁github

  • 下一頁vue-router

初始化時須要的配置有:vuex

  • totalPage(總頁數)數組

  • initPage(初始頁)app

  • showPrev(是否顯示上一頁)

  • showNext(是否顯示下一頁)

  • showItems(中間顯示幾頁)

  • showJump(是否顯示跳轉到第幾頁)

這些能夠經過vueprops來接收。

另外,pager組件自己須要有一個記錄當前頁的currentPagepages數組用來容納中間顯示的頁碼,jumpPage綁定輸入的跳轉頁碼。

基本實現

對應的代碼爲:

<template>
    <div class="pager-wrapper" v-if="totalPage > 0">
        <div class="pager-pages">
            <a v-show="currentPage > 1 && showPrev" @click="go(currentPage - 1)">上一頁</a>
            <a :class="{active: currentPage == 1 ? true : false}" @click="go(1)">1</a>
            <strong v-show="pages[0] > 2">...</strong>
            <a v-for="page in pages" :class="{active: currentPage == page ? true : false}" @click="go(page)">{{page}}</a>
            <strong v-show="pages[pages.length-1] < totalPage - 1">...</strong>
            <a v-if="totalPage > 1" :class="{active: currentPage == totalPage ? true : false}" @click="go(totalPage)">{{totalPage}}</a>
            <a v-show="currentPage < totalPage && showNext" @click="go(currentPage + 1)">下一頁</a>
        </div>
        <div v-if="showJump" v-show="totalPage > 1" class="pager-jump">
            <span>共<em class="jump-total">{{totalPage}}</em>頁 ,跳至</span>
            <input type="number" min="1" :max="totalPage" v-model="jumpPage" class="jump-input">
            <span>頁</span>
            <a @click="go(jumpPage)">肯定</a>
        </div>
    </div>
</template>
<script>
  export default {
        props: {
            totalPage: { // 總頁數
                type: Number,
                default: 1,
                required: true
            },
            showItems: { // 顯示出來的頁數,如: 1 ... 34[5]67 ... 10
                type: Number,
                default: 5
            },
            showPrev: { // 是否顯示「上一頁」
                type: Boolean,
                default: true
            },
            showNext: { // 是否顯示「下一頁」
                type: Boolean,
                default: true
            },
            showJump: { // 是否顯示「跳轉」
                type: Boolean,
                default: true
            },
            initPage: {
                type: Number,
                default: 1
            }
        },
        data () {
            return {
                currentPage: 0,
                pages: [],
                jumpPage: 0,
            }
        },
        created () {// 初始化時currentPage賦值
            this.currentPage = this.initPage
        }
        methods: {
            go (page) {
                if(page < 1) {
                    page = 1
                }
                if(page > this.totalPage) {
                    page = this.totalPage
                }
                if(page === this.currentPage) {
                    return
                }
                this.currentPage = parseInt(page,10)
                this.$emit('go-page',{
                    page: this.currentPage
                })
            }
        },
        watch: {
            currentPage (newVal) {
                this.jumpPage = newVal
            },
            initPage (newVal) {
                if(this.currentPage !== newVal) {
                    this.currentPage = newVal
                }
            }
        }
    }
</script>

接下來就是pages數組的值如何獲取到。因爲pages始終是跟當前頁currentPage以及配置中須要顯示的showItems強相關的,那麼徹底能夠將pages改成計算屬性:

computed: {
    pages () {
        // 根據起始頁碼和結束頁碼獲得頁碼數組
        let getPages = (start,end) => {
            if(start <= 1 || start > end || start >= this.totalPage) {
                start = 2
            }
            if(end >= this.totalPage || end < start || end <= 1) {
                end = this.totalPage - 1
            }
            let arr = []
            for(let i = start; i <= end; i++) {
                arr.push(i)
            }
            return arr
        }
        let counts = this.showItems
        if(this.totalPage < counts + 2) {
            return getPages(2,this.totalPage)
        } else {
            if(this.currentPage <= Math.ceil(counts/2)) {
                return getPages(2,counts)
            } else if(this.currentPage >= this.totalPage - Math.floor(counts/2)) {
                return getPages(this.totalPage + 1 - counts,this.totalPage - 1)
            } else {
                let half = Math.ceil(counts/2) - 1
                let end = this.currentPage + half
                if(counts % 2 === 0) {
                    end++
                }
                return getPages(this.currentPage - half,end)
            }
        }
    }
}

功能拓展

到這裏一個普通的翻頁組件基本上就實現了(樣式本身能夠去定製)。可是不少時候(特別是一些管理後臺),結合vue-router作成SPA,一般會有這樣的需求:

翻到某個列表的某一頁以後,點擊某一項到編輯頁,編輯完成後但願可以返回到跳轉以前的那一頁。

這個需求若是僅僅用上面的pager組件,實現起來就不是很方便。也許有人會說結合vuex能夠,可是這樣的話須要在state中記錄下跳轉前的頁碼。假若有不少個翻頁列表,就須要記錄多個,這顯然並不優雅。

不過由於vue-router實現的優雅,咱們要知足上面的需求也很簡單:
首先props上增長mode配置,因爲當modeparams時,跳轉須要知道是在哪個路由下,因此:

mode: {
    type: String,
    default: 'event' // 'event' | 'query' | 'params'
},
routeName: {
    type: String
}

而後再在實際跳轉的邏輯方法go(page)裏面,作點更改:

go (page) {
    if(page < 1) {
        page = 1
    }
    if(page > this.totalPage) {
        page = this.totalPage
    }
    if(page === this.currentPage) {
        return
    }
    this.currentPage = parseInt(page,10)
    if(this.mode == 'query') {
        let query = this.$route.query
        query.page = this.currentPage
        this.$router.go({query: query})
    } else if(this.mode == 'params') {
        let params = this.$route.params
        params.page = this.currentPage
        this.$router.go({name: this.routeName,params: params})
    } else {
        this.$emit('go-page',{
            page: this.currentPage
        })
    }
}

這樣基本上就完成了一個簡單且通用的翻頁組件啦,接下里就是發不到倉庫裏供你們使用了。
本文最終實現的翻頁組件已經發布,你們能夠看一波源碼:
vue-simple-pager

總結

整體上講的比較淺顯,但願能有幫助。

相關文章
相關標籤/搜索