|
First of all, the last wave of renderings: ![]() Basic elementsFirst of all, the elements commonly owned by the pager component (hereinafter referred to as the "pager component") are: The configurations required for initialization are: totalPage initPage showPrev (whether to show the previous page) showNext (whether to show the next page) showItems (a few pages in the middle) showJump (whether to show the jump to which page it goes to)
These can be received via vue's props. In addition, the pager component itself needs to have a currentPage that records the current page, the pages array is used to accommodate the page number displayed in the middle, and the jumpPage binds the jump page number input. Basic realizationThe corresponding code is:
<template>
<div class="pager-wrapper" v-if="totalPage > 0">
<div class="pager-pages">
<a v-show="currentPage > 1 && showPrev" @click="go(currentPage - 1)" > the previous page</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)" > next page</a>
</div>
<div v-if="showJump" v-show="totalPage > 1" class="pager-jump">
<span>Total <em class="jump-total">{{totalPage}}</em> page, jump to</span>
<input type="number" min="1" :max="totalPage" v-model="jumpPage" class="jump-input">
<span>page</span>
<a @click="go(jumpPage)" > determined</a>
</div>
</div>
</template>
<script>
export default {
props: {
totalPage: { // Total number of pages
type: Number,
default: 1,
required: true
},
showItems: { // Number of pages displayed, e.g.: 1 ... 34[5]67 ... 10
type: Number,
default: 5
},
showPrev: { // whether to show "Previous"
type: Boolean,
default: true
},
showNext: { // Whether to show "Next"
type: Boolean,
default: true
},
showJump: { // whether to show "Jump"
type: Boolean,
default: true
},
initPage: {
type: Number,
default: 1
}
},
data () {
return {
currentPage: 0,
pages: [],
jumpPage: 0,
}
},
created() {// currentPage assignment at initialization
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>
The next step is how to get the value of the pages array. Since pages are always strongly related to the current page and the showItems that need to be displayed in the configuration, it is entirely possible to change pages to a calculated property:
computed: {
pages () {
The page number array is obtained based on the start and end page numbers
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)
}
}
}
}
Functional expansionAt this point, an ordinary page-turning component is basically implemented (the style can be customized by itself). However, many times (especially some management backgrounds), combined with vue-router to make a SPA, there are usually such requirements: After flipping to a page in a certain list, click on an item to go to the edit page, and after editing, you want to be able to return to the page before jumping.
This requirement is not very convenient to implement if you only use the pager component above. Some people may say that it is okay to combine vuex, but in this case it is necessary to record the page number before the jump in the state. If there are many page flip lists, it is obviously not elegant to record multiple pages. However, because of the elegance of the Vue-Router implementation, it is easy to meet the above requirements: First, add the mode configuration on the props, because when the mode is params, the jump needs to know which route it is on, so:
mode: {
type: String,
default: 'event' // 'event' | 'query' | 'params'
},
routeName: {
type: String
}
Then make some changes in the actual jumping logic method 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
})
}
}
This basically completes a simple and universal page turning component, which cannot be sent to the repository for everyone to use. The page turning component finally implemented in this article has been released, and you can see a wave of source code:
vue-simple-pager
|