feat: 分页组件 (#327)

* feat: 分页组件

* feat: 代码规范化
This commit is contained in:
zgrong
2017-11-17 00:09:42 -06:00
committed by neverland
parent 0817411ae8
commit d17f161772
12 changed files with 16184 additions and 0 deletions
+3
View File
@@ -32,6 +32,7 @@ import Locale from './locale';
import NavBar from './nav-bar';
import NoticeBar from './notice-bar';
import NumberKeyboard from './number-keyboard';
import Pagination from './pagination';
import Panel from './panel';
import PasswordInput from './password-input';
import Picker from './picker';
@@ -92,6 +93,7 @@ const components = [
NavBar,
NoticeBar,
NumberKeyboard,
Pagination,
Panel,
PasswordInput,
Picker,
@@ -166,6 +168,7 @@ export {
NavBar,
NoticeBar,
NumberKeyboard,
Pagination,
Panel,
PasswordInput,
Picker,
+189
View File
@@ -0,0 +1,189 @@
<template>
<ul :class="['van-pagination', { 'van-pagination-simple': !isMultiMode }]">
<li
:class="[{ 'van-pagination--disabled': isNoPrevious } , 'van-pagination__item', 'van-pagination__prev', 'van-hairline']"
@click="selectPage(currentPage - 1, $event)"
>
{{ previousText }}
</li>
<li
v-if="isMultiMode"
v-for="(page, index) in pages"
:key="index"
:class="[{ 'van-pagination--active': page.active }, 'van-pagination__item', 'van-pagination__page', 'van-hairline']"
@click="selectPage(page.number, $event)"
>
{{ page.text }}
</li>
<li v-if="!isMultiMode" class="van-pagination__page-desc">
<slot name="pageDesc">{{ pageDesc }}</slot>
</li>
<li
:class="[{ 'van-pagination--disabled': isNoNext }, 'van-pagination__item', 'van-pagination__next', 'van-hairline']"
@click="selectPage(currentPage + 1, $event)"
>
{{ nextText }}
</li>
</ul>
</template>
<script>
export default {
name: 'van-pagination',
props: {
mode: {
type: String,
default: 'multi'
},
forceEllipses: Boolean,
itemsPerPage: {
type: Number,
default: 10
},
showPageSize: {
type: Number,
default: 5,
validator: value => typeof value === 'number' && value >= 1
},
/* vModel { currentPage: 1, numPages: 10 } */
value: {
type: Object,
required: true,
validator: function(value) {
return (
value &&
value.currentPage != undefined &&
typeof value.currentPage === 'number'
);
}
},
previousText: {
type: String,
default: 'Previous'
},
nextText: {
type: String,
default: 'Next'
},
totalItems: {
type: Number,
default: 0
}
},
data() {
const currentPage = this.value.currentPage !== undefined ? this.value.currentPage : 1;
let totalPages = this.itemsPerPage < 1 ? 1 : Math.ceil(this.totalItems / this.itemsPerPage);
totalPages = Math.max(totalPages, 1);
return { currentPage, totalPages };
},
computed: {
isMultiMode() {
return this.mode === 'multi';
},
isNoPrevious() {
return this.value.currentPage === 1;
},
isNoNext() {
return this.value.currentPage === this.totalPages;
},
pages() {
const pages = [];
if (this.currentPage <= 0 || this.currentPage > this.totalPages) {
return pages;
}
// Default page limits
let startPage = 1,
endPage = this.totalPages;
const isMaxSized = this.showPageSize !== undefined && this.showPageSize < this.totalPages;
// recompute if showPageSize
if (isMaxSized) {
// Current page is displayed in the middle of the visible ones
startPage = Math.max(
this.currentPage - Math.floor(this.showPageSize / 2),
1
);
endPage = startPage + this.showPageSize - 1;
// Adjust if limit is exceeded
if (endPage > this.totalPages) {
endPage = this.totalPages;
startPage = endPage - this.showPageSize + 1;
}
}
// Add page number links
for (let number = startPage; number <= endPage; number++) {
let page = this.makePage(number, number, number === this.currentPage);
pages.push(page);
}
// Add links to move between page sets
if (isMaxSized && this.showPageSize > 0 && this.forceEllipses) {
if (startPage > 1) {
//need ellipsis for all options unless range is too close to beginning
let previousPageSet = this.makePage(startPage - 1, '...', false);
pages.unshift(previousPageSet);
}
if (endPage < this.totalPages) {
//need ellipsis for all options unless range is too close to end
let nextPageSet = this.makePage(endPage + 1, '...', false);
pages.push(nextPageSet);
}
}
return pages;
},
pageDesc() {
return this.currentPage + '/' + this.totalPages;
}
},
created() {
// 初始value值
this.triggerInput();
},
watch: {
'value.currentPage'(value, oldValue) {
this.currentPage = value;
this.$emit('change');
}
},
methods: {
selectPage(page, evt) {
if (this.currentPage !== page && page > 0 && page <= this.totalPages) {
this.currentPage = page;
}
this.triggerInput();
},
triggerInput() {
// Emit the new data to the parent.
this.$emit('input', this.createDataForModel(this.currentPage, this.totalPages));
},
makePage(number, text, active) {
return { number, text, active };
},
createDataForModel(currentPage, numPages) {
let data = { currentPage, numPages };
return data;
}
}
};
</script>
+1
View File
@@ -18,6 +18,7 @@
@import './notice-bar.css';
@import './popup.css';
@import './search.css';
@import './pagination.css';
@import './panel.css';
@import './steps.css';
@import './tag.css';
+74
View File
@@ -0,0 +1,74 @@
@import './common/var.css';
.van-pagination {
display: flex;
text-align: center;
line-height: 40px;
font-size: 14px;
&__item {
flex: 1;
height: 40px;
min-width: 36px;
color: $blue;
background-color: $white;
box-sizing: border-box;
user-select: none;
&:active {
background-color: $blue;
color: $white;
opacity: 0.8;
}
&::after {
border-width: 1px 0 1px 1px;
}
&:last-child::after {
border-right-width: 1px;
}
}
&__prev,
&__next {
&.van-pagination__item {
padding: 0 5px;
}
}
&__page {
flex-grow: 0;
&.van-pagination--active {
background-color: $blue;
color: $white;
}
}
&--disabled {
&.van-pagination__item {
background-color: $background-color;
color: $gray-darker;
opacity: 0.6;
}
}
&__page-desc {
flex: 1;
height: 40px;
color: $gray-darker;
}
}
.van-pagination-simple {
.van-pagination__prev,
.van-pagination__next {
&.van-pagination__item::after {
border-width: 1px;
}
}
}