如何使用 Vue.js 构建可重用的分页组件

介绍

Pagination 是将大型结果分成单独页面的解决方案,并为用户提供导航工具来显示这些页面。

网页资源在Web应用程序中可以非常有用,不仅在性能方面,而且从用户体验的角度。

在本文中,您将学习如何创建一个动态且可重复使用的 Vue.js 页面组件。

前提条件

要完成本教程,您将需要:

本教程已通过 Node v16.4.0、npm v7.19.0 和 Vue v2.6.11 进行验证。

步骤 1 - 设置项目

页面组件应该允许用户进入第一页和最后一页,前进和后退,并直接切换到近范围的页面。

我们想渲染一个按钮,进入第一个页面,前一个页面,页面范围,下一个页面和最后一个:

1[first] [next] [1] [2] [3] [previous] [last]

大多数应用程序每次用户更改页面时都会发出API请求,我们需要确保我们的组件允许我们这样做,但我们不希望在组件中发出请求,这样我们就会确保该组件在整个应用程序中可重复使用,并且请求全部在操作 / 服务层中进行。

在 API 终端上实现页面化有几种可能的方法。

如果API只提供记录总数的信息,我们可以通过将结果数以每页的结果数分开来计算页面总数: totalResults / perPage

对于这个例子,让我们假设我们的API告诉我们每页的结果数(‘PerPage’)、页面总数(‘TotalPages’)、当前页面(‘currentPage’)。

虽然我们想要渲染一系列页面,但我们不希望渲染所有可用的页面. 让我们也允许在我们的组件中配置最多可见按钮(‘maxVisibleButtons’)。

现在我们知道我们希望我们的组件做什么以及我们需要哪些数据,我们可以设置HTML结构和所需的补丁。

您可以使用@vue/cli创建一个新的Vue项目:

1npx @vue/cli create --default vue-pagination-example

然后导航到新创建的项目目录;

1cd vue-pagination-example

创建一个Pagination.vue文件,并使用代码编辑器打开它:

 1[label src/components/Pagination.vue]
 2<template>
 3  <ul>
 4    <li>
 5      <button
 6        type="button"
 7      >
 8        First
 9      </button>
10    </li>
11
12    <li>
13      <button
14        type="button"
15      >
16        Previous
17      </button>
18    </li>
19
20    <!-- Visible Buttons Start -->
21
22    <!-- ... -->
23
24    <!-- Visible Buttons End -->
25
26    <li>
27      <button
28        type="button"
29      >
30        Next
31      </button>
32    </li>
33
34    <li>
35      <button
36        type="button"
37      >
38        Last
39      </button>
40    </li>
41  </ul>
42</template>
43
44<script>
45export default {
46  props: {
47    maxVisibleButtons: {
48      type: Number,
49      required: false,
50      default: 3
51    },    
52    totalPages: {
53      type: Number,
54      required: true
55    },
56    perPage: {
57      type: Number,
58      required: true
59    },
60    currentPage: {
61      type: Number,
62      required: true
63    }
64  }
65};
66</script>

在此时,您的组件将在列表中显示四个按钮. 为了获得可见按钮的范围,我们将使用一个循环。

我们需要确保这个数字永远不会超过设置可见按钮的最大数目,也不会超过可用的页数。

我们的循环的开始号码取决于当前的页面:

  1. 当当前页面是第一个时,让我们向用户显示当前页面和下一个页面 2.当当前页面是最后一个页面时,让我们显示最后一页和之前的页面 3.对于之间的一切,让我们显示前一页和下一页(s)。

我们的循环的终结数字也需要一些计算。我们需要在页面总数和我们想要停止的位置之间获得最小的数字。 要计算我们想要停止的位置,我们需要开始位置的总和,加上可见按钮的最大数目。

让我们使用一个计算属性,返回一系列具有可见页面的对象. 每个对象将有页面号码的支持,另一个会告诉我们按钮是否应该被禁用。

对于更复杂的数据结构,建议为每个v-for提供一个钥匙。Vue使用钥匙值来查找需要更新的元素,当这个值不提供时,Vue使用现场补丁策略。尽管我们使用的数据足够简单,让我们提供钥匙值 - 如果您使用了eslint-vue-plugin(LINK1)与vue3-essential(LINK2)的规则,您将始终需要提供钥匙的值。

修订Pagination.vue文件并添加startPage()pages():

 1[label src/components/Pagination.vue]
 2<template>
 3  <ul>
 4    ...
 5    <!-- Visible Buttons Start -->
 6
 7    <li
 8      v-for="page in pages"
 9      :key="page.name"
10    >
11      <button
12        type="button"
13        :disabled="page.isDisabled"
14      >
15        {{ page.name }}
16      </button>
17    </li>
18
19    <!-- Visible Buttons End -->
20    ...
21  </ul>
22</template>
23
24<script>
25export default {
26  ...
27  computed: {
28    startPage() {
29      // When on the first page
30      if (this.currentPage === 1) {
31        return 1;
32      }
33
34      // When on the last page
35      if (this.currentPage === this.totalPages) {
36        return this.totalPages - this.maxVisibleButtons;
37      }
38
39      // When inbetween
40      return this.currentPage - 1;
41    },
42    pages() {
43      const range = [];
44
45      for (
46        let i = this.startPage;
47        i <= Math.min(this.startPage + this.maxVisibleButtons - 1, this.totalPages);
48        i++
49      ) {
50        range.push({
51          name: i,
52          isDisabled: i === this.currentPage
53        });
54      }
55
56      return range;
57    },
58  }
59};
60</script>

现在,最大可见按钮的逻辑结束了。

步骤 2 — 添加事件听众

现在我们需要通知主组件,用户点击按钮时,用户点击了哪个按钮。

我们需要在每个按钮中添加一个事件倾听器。 v-on 指令允许听到 DOM 事件。

为了通知家长,我们将使用 $emit 方法发出页面点击的事件。

另外,要确保页面定位按钮仅在页面可用时是活跃的,这样做时,我们会使用 v-binddisabled 属性值与当前页面联系起来,我们也会使用 : 缩写为 `v-bind。

为了保持模板清洁,我们将使用计算属性来检查按钮是否应该被禁用. 使用计算属性也将缓存值,这意味着只要当前页面不会改变,对相同计算属性的其他请求将返回以前计算的结果,而无需再次运行该函数。

查看Pagination.vue文件,并为当前页面添加检查,然后单击事件方法:

 1[label src/components/Pagination.vue]
 2<template>
 3  <ul>
 4    <li>
 5      <button
 6        type="button"
 7        @click="onClickFirstPage"
 8        :disabled="isInFirstPage"
 9      >
10        First
11      </button>
12    </li>
13
14    <li>
15      <button
16        type="button"
17        @click="onClickPreviousPage"
18        :disabled="isInFirstPage"
19      >
20        Previous
21      </button>
22    </li>
23
24    <!-- Visible Buttons Start -->
25
26    <li
27      v-for="page in pages"
28      :key="page.name"
29    >
30      <button
31        type="button"
32        @click="onClickPage(page.name)"
33        :disabled="page.isDisabled"
34      >
35        {{ page.name }}
36      </button>
37    </li>
38
39    <!-- Visible Buttons End -->
40
41    <li>
42      <button
43        type="button"
44        @click="onClickNextPage"
45        :disabled="isInLastPage"
46      >
47        Next
48      </button>
49    </li>
50
51    <li>
52      <button
53        type="button"
54        @click="onClickLastPage"
55        :disabled="isInLastPage"
56      >
57        Last
58      </button>
59    </li>
60  </ul>
61</template>
62
63<script>
64export default {
65  ...
66  computed: {
67    ...
68    isInFirstPage() {
69      return this.currentPage === 1;
70    },
71    isInLastPage() {
72      return this.currentPage === this.totalPages;
73    },
74  },
75  methods: {
76    onClickFirstPage() {
77      this.$emit('pagechanged', 1);
78    },
79    onClickPreviousPage() {
80      this.$emit('pagechanged', this.currentPage - 1);
81    },
82    onClickPage(page) {
83      this.$emit('pagechanged', page);
84    },
85    onClickNextPage() {
86      this.$emit('pagechanged', this.currentPage + 1);
87    },
88    onClickLastPage() {
89      this.$emit('pagechanged', this.totalPages);
90    }
91  }
92}
93</script>

现在点击按钮的逻辑结束了。

步骤三:添加风格

现在我们的组件检查了我们最初想要的所有功能,我们需要添加一些CSS,使其看起来更像一个页面组件,而不是一个列表。

我们还希望我们的用户能够清楚地识别他们在哪个页面,让我们改变代表当前页面的按钮的颜色。

为了做到这一点,我们可以使用 object syntax将一个HTML class 绑定到我们的活跃页面按钮。当使用对象语法绑定类名称时,Vue 会自动切换类,当值发生变化。

虽然v-for中的每个块都有访问主范围属性,但我们会使用方法来检查页面是否活跃,以保持我们的模板清洁。

修订pagination.vue文件,并添加对活跃页面和 CSS 样式和类的检查:

 1[label src/components/Pagination.vue]
 2<template>
 3  <ul class="pagination">
 4    <li class="pagination-item">
 5      <button
 6        type="button"
 7        @click="onClickFirstPage"
 8        :disabled="isInFirstPage"
 9      >
10        First
11      </button>
12    </li>
13
14    <li class="pagination-item">
15      <button
16        type="button"
17        @click="onClickPreviousPage"
18        :disabled="isInFirstPage"
19      >
20        Previous
21      </button>
22    </li>
23
24    <!-- Visible Buttons Start -->
25
26    <li
27      v-for="page in pages"
28      class="pagination-item"
29    >
30      <button
31        type="button"
32        @click="onClickPage(page.name)"
33        :disabled="page.isDisabled"
34        :class="{ active: isPageActive(page.name) }"
35      >
36        {{ page.name }}
37      </button>
38    </li>
39
40    <!-- Visible Buttons End -->
41
42    <li class="pagination-item">
43      <button
44        type="button"
45        @click="onClickNextPage"
46        :disabled="isInLastPage"
47      >
48        Next
49      </button>
50    </li>
51
52    <li class="pagination-item">
53      <button
54        type="button"
55        @click="onClickLastPage"
56        :disabled="isInLastPage"
57      >
58        Last
59      </button>
60    </li>
61  </ul>
62</template>
63
64<script>
65export default {
66  ...
67  methods: {
68    ...
69    isPageActive(page) {
70      return this.currentPage === page;
71    }
72  }
73}
74</script>
75
76<style>
77.pagination {
78  list-style-type: none;
79}
80
81.pagination-item {
82  display: inline-block;
83}
84
85.active {
86  background-color: #4AAE9B;
87  color: #ffffff;
88}
89</style>

现在,设计活跃按钮的逻辑结束了。

步骤 4 – 使用组件

您需要通过提供总页每页的值来模拟 API 调用。

对于这个示例,‘currentPage’应该设置为‘1’,而‘onPageChange’将登录活跃页面。

 1[label src/App.vue]
 2<template>
 3  <div id="app">
 4    <pagination
 5      :totalPages="10"
 6      :perPage="10"
 7      :currentPage="currentPage"
 8      @pagechanged="onPageChange"
 9    />
10  </div>
11</template>
12
13<script>
14import Pagination from './components/Pagination.vue'
15
16export default {
17  name: 'App',
18  components: {
19    Pagination
20  },
21  data () {
22    return {
23      currentPage: 1,
24    };
25  },
26  methods: {
27    onPageChange(page) {
28      console.log(page)
29      this.currentPage = page;
30    }
31  }
32}
33</script>

在此时,您可以运行应用程序:

1npm run serve

在浏览器中打开应用程序并观察页面组件. 会出现一个 First, Previous, NextLast按钮. 在总共10页中,还会显示三个页面按钮. 因为第一个页面是当前页面,所以 1按钮被标记为一个活跃的类别。

一个实时代码示例在CodePen上可用

结论

在本文中,您了解如何创建一个动态且可重复使用的 Vue.js 页面组件。

如果您想了解有关 Vue.js 的更多信息,请参阅 我们的 Vue.js 主题页面以获取练习和编程项目。

Published At
Categories with 技术
Tagged with
comments powered by Disqus