Build a Reusable Pagination Component with Vue.js

综合技术 Alligator.io (源链)

Paginating resources in web applications can be very helpful not only performance-wise but also from a user experience perspective.

In this article you’ll learn how to create a dynamic and reusable Vue.js pagination component.

Base Structure

A pagination component should allow the user to go to the first and last pages, move forward and backwards and change directly to a page in a close range.

Most applications make an API request every time the user changes the page. We need to make sure our component allows to do so, but we don’t want to make the request within the component. This way we’ll make sure the component is reusable throughout the whole application and the request are all made in the actions/service layer. We can accomplish this by triggering an event with the number of the page the user clicked.

There are several possible ways to implement pagination on an API endpoint. For this example let’s assume our API informs us about the number of results per page, the total number of pages and the current page. These will be our dynamic props.

If, instead, the API only informs about the total number of records, we can calculate the total number of pages by dividing the number of results with the number of results per page: totalResults / resultsPerPage
.

We want to render a button to go to the first page, the previous one, range number of pages, next page and last one:

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

Although we want to render a range of pages, we do not want to render all available pages. Let’s also allow to configure the maximum number of visible buttons as a prop in our component.

Now that we know what we want our component to do and which data we’ll need, we can set the HTML structure and the needed props.

pagination.vue

export default {
  props: {
    maxVisibleButtons: {
      type: Number,
      required: false,
      default: 3
    },
    totalPages: {
      type: Number,
      required: true
    },
    total: {
      type: Number,
      required: true
    },
    currentPage: {
      type: Number,
      required: true
    }
  }
};


  

In order to get the range of visible pages we’ll use a for loop
.

We need to make sure the number is never bigger than the prop that sets the maximum number of visible buttons and also not bigger than the number of available pages.

The start number of our cycle depends on the current page:

  1. When the current page is the first one, let’s show the user the current one and the next ones.
  2. When the current page is the last one, let’s show the last page and the previous ones.
  3. For anything in between let’s show the previous page and the next one(s).

The end number of our cycle also needs some calculations. We need to get the smallest number between the total number of pages and the position where we want to stop. To calculate the position where where we want to stop, we need the sum of the position where we want to start plus the maximum number of visible buttons. Because we always want to show one button to the left hand of the current page, we need to subtract 1 from this number.

Let’s use a computed property that returns an array of objects with the range of visible pages. Each object will have a prop for the page number and another that will tell us whether the button should be disabled or not. After all we don’t want the user to click for the page he’s already on.

In order to render this array of pages we’ll use the v-for
directive. For more complex data structures, it’s recommended to provide a key
with each v-for
. Vue uses the key
value to find which element needs to be updated, when this value is not provided, Vue uses a “in-place patch” strategy. Although the data we are using is simple enough, let’s provide the key
value – if you useeslint-vue-plugin with the essential
rules, you will always need to provide the key
value.

pagination.vue

export default {
  ...
  computed: {
    startPage() {
      // When on the first page
      if (this.currentPage === 1) {
        return 1;
      }
      // When on the last page
      if (this.currentPage === this.totalPages) {
        return this.totalPages - this.maxVisibleButtons;
      }
      // When in between
      return this.currentPage - 1;
    },
    pages() {
      const range = [];

      for (let i = this.startPage;
        i <= Math.min(this.startPage + this.maxVisibleButtons - 1, this.totalPages);
        i+= 1 ) {
        range.push({
          name: i,
          isDisabled: i === this.currentPage
        });
      }

      return range;
    },
  }
};


  
    ...
  • ...

Event Listeners

Now we need to inform the parent component when the user clicks in a button and which button the user has clicked.

We need to add an event listener to each of our buttons. The
v-on
directive

allows to listen for DOM events. In this example I’ll use the
v-on
shorthand

to listen for the click event.

In order to inform the parent, we’ll use the $emit
method to emit an event with the page clicked.

Let’s also make sure the pagination buttons are only active if the page is available. In order to do so we’ll make use of v-bind
to bind the value of the disabled
attribute with the current page. We’ll also use the :
shorthand for v-bind.

In order to keep our template cleaner, we’ll use the computed properties to check if the button should be disabled. Using computed properties will also cache values, which means that as long as currentPage
won’t change, several access to the same computed property will return the previously computed result without having to run the function again.

pagination.vue

export default {
  ...
  computed: {
    isInFirstPage() {
      return this.currentPage === 1;
    },
    isInLastPage() {
      return this.currentPage === this.totalPages;
    },
  },
  methods: {
    onClickFirstPage() {
      this.$emit('pagechanged', 1);
    },
    onClickPreviousPage() {
      this.$emit('pagechanged', this.currentPage - 1);
    },
    onClickPage(page) {
      this.$emit('pagechanged', page);
    },
    onClickNextPage() {
      this.$emit('pagechanged', this.currentPage + 1);
    },
    onClickLastPage() {
      this.$emit('pagechanged', this.totalPages);
    }
  }
}


  

Styling

Now that our component checks all functionalities we initially wanted, we need to add some CSS to make it look more like a pagination component and less like a list.

We also want our users to be able to clearly identify which page they are on. Let’s change the color of the button representing the current page.

In order to so we can bind anHTML class to our active page button using the object syntax
. When using the object syntax to bind class names, Vue will automatically toggle the class when the value changes.

Although each block inside a v-for
has access to the parent scope properties, we’ll use a method
to check if the page is active in order to keep our template cleaner:

pagination.vue

export default {
  ...
  methods: {
    isPageActive(page) {
      return this.currentPage === page;
    }
  }
}


  
.pagination { list-style-type: none; } .pagination-item { display: inline-block; } .active { background-color: #4AAE9B; color: #ffffff; }

:tada: Our pagination component is ready! You can see the full source code for this component in this Codepen
.

您可能感兴趣的

Build a realtime cryptocurrency watcher PWA using ... PWAs (Progressive Web Applications) has already been identified as the future of web applications and the reason is quite obvious. PWAs let you build ...
Adding a “delete” link to a Vue component represen... This very much falls into the category of “things that must surely be easier”. So let me know in the comments if it is actually easier. Here’s th...
浅看wepy源码 (wepy 1.7.x) 原文地址及更多文章 - century's home 首先让我们先恭喜RNG,其次我们恭喜LGD(data, lol的玩家一个都不能得罪)。wepy是腾讯自家出品的一个小程序框架。小程序在代码体验上会和vue差不多,很多人从vue转向小程序可以说门槛非常低,但是小程序的开...
2018年中高级前端面试题目小结 前言 关于前端面试,及面试题目,我之前有很多文章总结过,可以在右侧搜索面试,进行查找。其实面试中可以问的问题很多,最近几年,我也面试过很多工作2-4年的前端,我一般会抓住他们做的项目,进行更详细的追问。所以,初中级前端面试的时候,除了掌握基础知识之外,项目中用到的技术要理清楚,假如你项目...
vue-awesome-form的实现及踩坑记录 最近实现了一个 vue-awesome-form 组件,主要功能是根据 json 来生成一个表单,支持同时渲染多个表单,表单嵌套,表单验证,对于一个简单的项目,生成表单只需要一个 json 就可以完成。而且有时候表单项不是前端写死的,而是由后端控制的,这个时候我们这个组件就派上用场了。 ...
责编内容来自:Alligator.io (源链) | 更多关于

阅读提示:酷辣虫无法对本内容的真实性提供任何保证,请自行验证并承担相关的风险与后果!
本站遵循[CC BY-NC-SA 4.0]。如您有版权、意见投诉等问题,请通过eMail联系我们处理。
酷辣虫 » Build a Reusable Pagination Component with Vue.js



专业 x 专注 x 聚合 x 分享 CC BY-NC-SA 4.0

使用声明 | 英豪名录