[Vue.js] encapsulate native pager components

Pagers are widely used in both foreground and background projects. Record the implementation process of encapsulating the native pager.

A component needs to be encapsulated. The most important thing is to determine what data it needs to dynamically obtain. To implement a pager, the following four data need to be transmitted externally:

1. What page is it now - pageNo

2. How much data need to be displayed on each page - pageSize

3. How much data is there - Total -- > how many pages are there - totalPage

4. The number of consecutive pages of the pager - the continuation is 5 / 7, which is generally odd (because of symmetry)

Create pagination Vue component first obtains the parameters passed by the parent component, that is, the four types mentioned above:

props: ['pageNo', 'pageSize', 'total', 'continues'],

The total number of pages can be calculated by the total number of data pieces / the number of data pieces displayed on each page. It needs to be rounded up and defined in the calculation attribute:

computed: {
    // Calculate the total number of pages
    countTotalPage() {
        return Math.ceil(this.total / this.pageSize);
    },
}

Then it is also the most cumbersome part of the pager implementation. It is necessary to calculate the start page and end page of continuous pages through the current number of pages and the number of continuous pages. Issues to consider:

1) the total number of pages is less than the number of consecutive pages. At present, it is not necessary to calculate the start page and end page;

2) if the total number of pages is greater than the number of consecutive pages, judge after calculating the start page and the end page;

- if the start page is less than 1;

- if the end page is greater than the total number of pages;

Also use calculated attributes:

props: ['pageNo', 'pageSize', 'total', 'continues'],
computed:{
    startNumAndEndNum() {
        let start = 0,
            end = 0;

        if (this.continues > this.countTotalPage) {
            // The total number of pages is less than consecutive pages
            start = 1;
            end = this.countTotalPage;
        } else {
            // The total number of pages is greater than the number of consecutive pages (normal)
            start = this.pageNo - Math.floor(this.continues / 2);
            end = this.pageNo + Math.floor(this.continues / 2);
            // Start page is less than 1
            if (start <= 0) {
                start = 1;
                end = this.continues;
            }
            // The end page is greater than the maximum number of pages
            if (end > this.countTotalPage) {
                start = this.countTotalPage - this.continues + 1;
                end = this.countTotalPage;
            }
        }
        return {
            start,
            end
        };
    },
}

The logic of the above code is summarized as follows:

Save the number of consecutive pages for page traversal through the start page and end page of consecutive pages

computed:{
    showPages() {
        let pages = [];
        for (let i = this.startNumAndEndNum.start; i <= this.startNumAndEndNum.end; i++) {
            pages.push(i);
        }
        return pages;
    }
}

 

Finally, the page structure and style:

The following points should be noted:

1. When start is 1, there is no need to display "1" button and "... Button"

2. When start is 2, there is no need to display "..." Button

3. When start is greater than 2, the "1" button and "... Button" need to be displayed

4. When end is the total number of pages, there is no need to display the "total pages" button and the "... Button"

5. When end is the total number of pages - 1, the "... Button" does not need to be displayed

6. When end is less than - 1 of the total pages, the "total pages" button and "... Button" need to be displayed

The above six points are the six situations that should be paid attention to in page conditional rendering v-show.

In addition, clicking the specified page number requires a user-defined event to notify the parent component to modify the current page

<!-- upper part -->
<button @click="$emit('sendPageNo',pageNo-1)" :disabled="pageNo===1">previous page</button>
<button 
        v-show="startNumAndEndNum.start>1" 
        @click="$emit('sendPageNo',1)"
        :class="{active:pageNo===1}"
        >1</button>
<button v-show="startNumAndEndNum.start>2">···</button>

<!-- Middle part -->
<button 
        v-for="(page,index) in showPages" 
        :key="index" 
        @click="$emit('sendPageNo',page)"
        :class="{active:pageNo===page}"
        >
    {{page}}
</button>

<!-- lower part -->
<button v-show="startNumAndEndNum.end < countTotalPage - 1">···</button>
<button 
        v-show="startNumAndEndNum.end < countTotalPage" 
        @click="$emit('sendPageNo',countTotalPage)"
        :class="{active:pageNo===countTotalPage}"
        >
    {{countTotalPage}}
</button>
<button @click="$emit('sendPageNo',pageNo+1)" :disabled="pageNo===countTotalPage">next page</button>

<!-- total -->
<button style="margin-left: 30px">common {{total}} strip</button>

css

<style lang="less" scoped>
    .pagination {
        button {
            margin: 0 5px;
            background-color: #f4f4f5;
            color: #606266;
            outline: none;
            border-radius: 2px;
            padding: 0 4px;
            vertical-align: top;
            display: inline-block;
            font-size: 13px;
            min-width: 35.5px;
            height: 28px;
            line-height: 28px;
            cursor: pointer;
            box-sizing: border-box;
            text-align: center;
            border: 0;

            &[disabled] {
                color: #c0c4cc;
                cursor: not-allowed;
            }

            &.active {
                cursor: not-allowed;
                background-color: #409eff;
                color: #fff;
            }
        }
    }
</style>

js code:

<script>
    export default {
        name: "Pagination",
        props: ['pageNo', 'pageSize', 'total', 'continues'],
        computed: {
            // Calculate the total number of pages
            countTotalPage() {
                return Math.ceil(this.total / this.pageSize);
            },
            // Calculate the start page and end page of the number of consecutive page numbers of the pager
            startNumAndEndNum() {
                let start = 0,
                    end = 0;

                if (this.continues > this.countTotalPage) {
                    // The total number of pages is less than consecutive pages
                    start = 1;
                    end = this.countTotalPage;
                } else {
                    // The total number of pages is greater than the number of consecutive pages (normal)
                    start = this.pageNo - Math.floor(this.continues / 2);
                    end = this.pageNo + Math.floor(this.continues / 2);
                    // Start page is less than 1
                    if (start <= 0) {
                        start = 1;
                        end = this.continues;
                    }
                    // The end page is greater than the maximum number of pages
                    if (end > this.countTotalPage) {
                        start = this.countTotalPage - this.continues + 1;
                        end = this.countTotalPage;
                    }
                }
                return {
                    start,
                    end
                };
            },
            // Calculate the number of pages displayed
            showPages() {
                let pages = [];
                this.startNumAndEndNum
                for (let i = this.startNumAndEndNum.start; i <= this.startNumAndEndNum.end; i++) {
                    pages.push(i);

                }
                return pages;
            }
        }
    }
</script>

Use current component:

<Pagination class="pagination" 
            :pageNo="searchParams.pageNo" 
            :pageSize="searchParams.pageSize" 
            :total="total" 
            :continues="5"
            @sendPageNo="handleSendPageNo"
/>

Keywords: Javascript Front-end Vue.js

Added by computerzworld on Thu, 17 Feb 2022 03:31:39 +0200