diff --git a/src-next/pagination/README.md b/src-next/pagination/README.md
new file mode 100644
index 000000000..42ca945df
--- /dev/null
+++ b/src-next/pagination/README.md
@@ -0,0 +1,67 @@
+# Pagination
+
+### Install
+
+```js
+import Vue from 'vue';
+import { Pagination } from 'vant';
+
+Vue.use(Pagination);
+```
+
+## Usage
+
+### Basic Usage
+
+```html
+
+```
+
+```js
+export default {
+ data() {
+ return {
+ currentPage: 1,
+ };
+ },
+};
+```
+
+### Simple mode
+
+```html
+
+```
+
+### Show ellipses
+
+```html
+
+```
+
+## API
+
+### Props
+
+| Attribute | Description | Type | Default |
+| --- | --- | --- | --- |
+| v-model | Current page number | _number_ | - |
+| mode | Mode, can be set to `simple` `multi` | _string_ | `multi` |
+| prev-text | Previous text | _string_ | `Previous` |
+| next-text | Next text | _string_ | `Next` |
+| total-items | Total items | _number \| string_ | `0` |
+| items-per-page | Item number per page | _number \| string_ | `10` |
+| page-count | The total number of pages, if not set, will be calculated based on `total-items` and `items-per-page` | _number \| string_ | `-` |
+| show-page-size | Count of page size to show | _number \| string_ | `5` |
+| force-ellipses | Whether to show ellipses | _boolean_ | `false` |
+
+### Events
+
+| Event | Description | Arguments |
+| ------ | ------------------------ | --------- |
+| change | Triggered on page change | - |
diff --git a/src-next/pagination/README.zh-CN.md b/src-next/pagination/README.zh-CN.md
new file mode 100644
index 000000000..89a5dcb44
--- /dev/null
+++ b/src-next/pagination/README.zh-CN.md
@@ -0,0 +1,67 @@
+# Pagination 分页
+
+### 引入
+
+```js
+import Vue from 'vue';
+import { Pagination } from 'vant';
+
+Vue.use(Pagination);
+```
+
+## 代码演示
+
+### 基础用法
+
+```html
+
+```
+
+```js
+export default {
+ data() {
+ return {
+ currentPage: 1,
+ };
+ },
+};
+```
+
+### 简单模式
+
+```html
+
+```
+
+### 显示省略号
+
+```html
+
+```
+
+## API
+
+### Props
+
+| 参数 | 说明 | 类型 | 默认值 |
+| --- | --- | --- | --- |
+| v-model | 当前页码 | _number_ | - |
+| mode | 显示模式,可选值为 `simple` | _string_ | `multi` |
+| prev-text | 上一页按钮文字 | _string_ | `上一页` |
+| next-text | 下一页按钮文字 | _string_ | `下一页` |
+| page-count | 总页数 | _number \| string_ | 根据页数计算 |
+| total-items | 总记录数 | _number \| string_ | `0` |
+| items-per-page | 每页记录数 | _number \| string_ | `10` |
+| show-page-size | 显示的页码个数 | _number \| string_ | `5` |
+| force-ellipses | 是否显示省略号 | _boolean_ | `false` |
+
+### Events
+
+| 事件名 | 说明 | 回调参数 |
+| ------ | -------------- | -------- |
+| change | 页码改变时触发 | - |
diff --git a/src-next/pagination/demo/index.vue b/src-next/pagination/demo/index.vue
new file mode 100644
index 000000000..d579d6819
--- /dev/null
+++ b/src-next/pagination/demo/index.vue
@@ -0,0 +1,81 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src-next/pagination/index.js b/src-next/pagination/index.js
new file mode 100644
index 000000000..0aef4e5f1
--- /dev/null
+++ b/src-next/pagination/index.js
@@ -0,0 +1,164 @@
+import { createNamespace } from '../utils';
+import { BORDER } from '../utils/constant';
+
+const [createComponent, bem, t] = createNamespace('pagination');
+
+function makePage(number, text, active) {
+ return { number, text, active };
+}
+
+export default createComponent({
+ props: {
+ prevText: String,
+ nextText: String,
+ forceEllipses: Boolean,
+ mode: {
+ type: String,
+ default: 'multi',
+ },
+ modelValue: {
+ type: Number,
+ default: 0,
+ },
+ pageCount: {
+ type: [Number, String],
+ default: 0,
+ },
+ totalItems: {
+ type: [Number, String],
+ default: 0,
+ },
+ itemsPerPage: {
+ type: [Number, String],
+ default: 10,
+ },
+ showPageSize: {
+ type: [Number, String],
+ default: 5,
+ },
+ },
+
+ computed: {
+ count() {
+ const count =
+ this.pageCount || Math.ceil(this.totalItems / this.itemsPerPage);
+ return Math.max(1, count);
+ },
+
+ pages() {
+ const pages = [];
+ const pageCount = this.count;
+ const showPageSize = +this.showPageSize;
+
+ if (this.mode !== 'multi') {
+ return pages;
+ }
+
+ // Default page limits
+ let startPage = 1;
+ let endPage = pageCount;
+ const isMaxSized = showPageSize < pageCount;
+
+ // recompute if showPageSize
+ if (isMaxSized) {
+ // Current page is displayed in the middle of the visible ones
+ startPage = Math.max(this.modelValue - Math.floor(showPageSize / 2), 1);
+ endPage = startPage + showPageSize - 1;
+
+ // Adjust if limit is exceeded
+ if (endPage > pageCount) {
+ endPage = pageCount;
+ startPage = endPage - showPageSize + 1;
+ }
+ }
+
+ // Add page number links
+ for (let number = startPage; number <= endPage; number++) {
+ const page = makePage(number, number, number === this.modelValue);
+ pages.push(page);
+ }
+
+ // Add links to move between page sets
+ if (isMaxSized && showPageSize > 0 && this.forceEllipses) {
+ if (startPage > 1) {
+ const previousPageSet = makePage(startPage - 1, '...', false);
+ pages.unshift(previousPageSet);
+ }
+
+ if (endPage < pageCount) {
+ const nextPageSet = makePage(endPage + 1, '...', false);
+ pages.push(nextPageSet);
+ }
+ }
+
+ return pages;
+ },
+ },
+
+ watch: {
+ modelValue: {
+ handler(page) {
+ this.select(page);
+ },
+ immediate: true,
+ },
+ },
+
+ methods: {
+ select(page, emitChange) {
+ page = Math.min(this.count, Math.max(1, page));
+ if (this.modelValue !== page) {
+ this.$emit('update:modelValue', page);
+
+ if (emitChange) {
+ this.$emit('change', page);
+ }
+ }
+ },
+ },
+
+ render() {
+ const value = this.modelValue;
+ const simple = this.mode !== 'multi';
+
+ const onSelect = (value) => () => {
+ this.select(value, true);
+ };
+
+ return (
+
+ -
+ {this.prevText || t('prev')}
+
+ {this.pages.map((page) => (
+ -
+ {page.text}
+
+ ))}
+ {simple && (
+ -
+ {this.$slots.pageDesc
+ ? this.$slots.pageDesc()
+ : `${value}/${this.count}`}
+
+ )}
+ -
+ {this.nextText || t('next')}
+
+
+ );
+ },
+});
diff --git a/src-next/pagination/index.less b/src-next/pagination/index.less
new file mode 100644
index 000000000..862b1677c
--- /dev/null
+++ b/src-next/pagination/index.less
@@ -0,0 +1,77 @@
+@import '../style/var';
+
+.van-pagination {
+ display: flex;
+ font-size: @pagination-font-size;
+
+ &__item,
+ &__page-desc {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ }
+
+ &__item {
+ flex: 1;
+ box-sizing: border-box;
+ min-width: @pagination-item-width;
+ height: @pagination-height;
+ color: @pagination-item-default-color;
+ background-color: @pagination-background-color;
+ cursor: pointer;
+ user-select: none;
+
+ &:active {
+ color: @white;
+ background-color: @pagination-item-default-color;
+ }
+
+ &::after {
+ border-width: @border-width-base 0 @border-width-base @border-width-base;
+ }
+
+ &:last-child::after {
+ border-right-width: @border-width-base;
+ }
+
+ &--active {
+ color: @white;
+ background-color: @pagination-item-default-color;
+ }
+ }
+
+ &__prev,
+ &__next {
+ padding: 0 @padding-base;
+ cursor: pointer;
+ }
+
+ &__item--disabled {
+ &,
+ &:active {
+ color: @pagination-item-disabled-color;
+ background-color: @pagination-item-disabled-background-color;
+ cursor: not-allowed;
+ opacity: @pagination-disabled-opacity;
+ }
+ }
+
+ &__page {
+ flex-grow: 0;
+ }
+
+ &__page-desc {
+ flex: 1;
+ height: @pagination-height;
+ color: @pagination-desc-color;
+ }
+
+ &--simple {
+ .van-pagination__prev,
+ .van-pagination__next {
+ &::after {
+ border-width: @border-width-base;
+ }
+ }
+ }
+}
diff --git a/src-next/pagination/test/__snapshots__/demo.spec.js.snap b/src-next/pagination/test/__snapshots__/demo.spec.js.snap
new file mode 100644
index 000000000..c4e54ef49
--- /dev/null
+++ b/src-next/pagination/test/__snapshots__/demo.spec.js.snap
@@ -0,0 +1,34 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`renders demo correctly 1`] = `
+
+`;
diff --git a/src-next/pagination/test/demo.spec.js b/src-next/pagination/test/demo.spec.js
new file mode 100644
index 000000000..5c70922b5
--- /dev/null
+++ b/src-next/pagination/test/demo.spec.js
@@ -0,0 +1,4 @@
+import Demo from '../demo';
+import { snapshotDemo } from '../../../test/demo';
+
+snapshotDemo(Demo);
diff --git a/vant.config.js b/vant.config.js
index d5eaad36d..8bc31a38e 100644
--- a/vant.config.js
+++ b/vant.config.js
@@ -298,10 +298,10 @@ module.exports = {
path: 'nav-bar',
title: 'NavBar 导航栏',
},
- // {
- // path: 'pagination',
- // title: 'Pagination 分页',
- // },
+ {
+ path: 'pagination',
+ title: 'Pagination 分页',
+ },
// {
// path: 'sidebar',
// title: 'Sidebar 侧边导航',
@@ -632,10 +632,10 @@ module.exports = {
path: 'nav-bar',
title: 'NavBar',
},
- // {
- // path: 'pagination',
- // title: 'Pagination',
- // },
+ {
+ path: 'pagination',
+ title: 'Pagination',
+ },
// {
// path: 'sidebar',
// title: 'Sidebar',