Cómo crear un componente de paginación reutilizable con Vue.js

Introducción

Índice
  1. Introducción
  • Prerrequisitos
  • Paso 1: Configuración del proyecto
  • Paso 2: agregar detectores de eventos
  • Paso 3: Agregar estilos
  • Paso 4: Uso del componente
  • Conclusión
  • La paginación es una solución para dividir resultados grandes en páginas separadas y se proporcionan al usuario herramientas de navegación para mostrar estas páginas.

    La paginación de recursos en aplicaciones web puede ser muy útil no sólo desde la perspectiva del rendimiento sino también desde la perspectiva de la experiencia del usuario.

    En este artículo, aprenderá cómo crear un componente de paginación Vue.js dinámico y reutilizable.

    Prerrequisitos

    Para completar este tutorial, necesitarás:

    • Node.js instalado localmente, lo cual puedes hacer siguiendo Cómo instalar Node.js y crear un entorno de desarrollo local .
    • Algunos conocimientos sobre la configuración de un proyecto Vue.js.

    Este tutorial fue verificado con Node v16.4.0, npmv7.19.0 y Vue v2.6.11.

    Paso 1: Configuración del proyecto

    Un componente de paginación debería permitir al usuario ir a la primera y última página, avanzar y retroceder, y cambiar directamente a una página cercana.

    Queremos renderizar un botón para ir a la primera página, la anterior, rango de número de páginas, página siguiente y última:

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

    La mayoría de las aplicaciones realizan una solicitud de API cada vez que el usuario cambia la página. Debemos asegurarnos de que nuestro componente nos permita hacerlo, pero no queremos realizar la solicitud dentro del componente. De esta manera, nos aseguraremos de que el componente sea reutilizable en toda la aplicación y que la solicitud se realice en la capa de acciones/servicio. Podemos lograr esto activando un evento con el número de la página en la que el usuario hizo clic.

    Hay varias formas posibles de implementar la paginación en un punto final de API.

    Si la API solo informa sobre el número total de registros, podemos calcular el número total de páginas dividiendo el número de resultados por el número de resultados por página: totalResults / perPage.

    Para este ejemplo, supongamos que nuestra API nos informa sobre la cantidad de resultados por página ( perPage), la cantidad total de páginas ( totalPages) y la página actual ( currentPage). Estas serán nuestras propiedades dinámicas.

    Aunque queremos mostrar un rango de páginas, no queremos mostrar todas las páginas disponibles. También permitiremos configurar la cantidad máxima de botones visibles como una propiedad en nuestro componente ( maxVisibleButtons).

    Ahora que sabemos qué queremos que haga nuestro componente y qué datos necesitaremos, podemos establecer la estructura HTML y las propiedades necesarias.

    Puedes usar @vue/clipara crear un nuevo proyecto Vue:

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

    Luego navegue hasta el directorio del proyecto recién creado;

    1. cd vue-pagination-example

    Crea un Pagination.vuearchivo y ábrelo con tu editor de código:

    src/componentes/Paginación.vue

    template  ul    li      button        type="button"              First      /button    /li    li      button        type="button"              Previous      /button    /li    !-- Visible Buttons Start --    !-- ... --    !-- Visible Buttons End --    li      button        type="button"              Next      /button    /li    li      button        type="button"              Last      /button    /li  /ul/templatescriptexport default {  props: {    maxVisibleButtons: {      type: Number,      required: false,      default: 3    },        totalPages: {      type: Number,      required: true    },    perPage: {      type: Number,      required: true    },    currentPage: {      type: Number,      required: true    }  }};/script

    En este punto, el componente mostrará cuatro botones en una lista. Para obtener el rango de botones visibles, utilizaremos un forbucle.

    Debemos asegurarnos de que el número nunca sea mayor que la propiedad que establece el número máximo de botones visibles y tampoco mayor que el número de páginas disponibles.

    El número de inicio de nuestro ciclo depende de la página actual:

    1. Cuando la página actual es la primera, mostramos al usuario la actual y las siguientes.
    2. Cuando la página actual sea la última, mostramos la última página y las anteriores.
    3. Para cualquier cosa entre medio, mostremos la página anterior y la(s) siguiente(s).

    El número final de nuestro ciclo también necesita algunos cálculos. Necesitamos obtener el número más pequeño entre el número total de páginas y la posición en la que queremos parar. Para calcular la posición en la que queremos parar, necesitamos la suma de la posición en la que queremos empezar más el número máximo de botones visibles. Como siempre queremos mostrar un botón a la izquierda de la página actual, necesitamos restar 1 a este número.

    Utilicemos una propiedad calculada que devuelva una matriz de objetos con un rango de páginas visibles. Cada objeto tendrá una propiedad para el número de página y otra que nos indicará si el botón debe estar deshabilitado o no. Después de todo, no queremos que el usuario haga clic en la página en la que ya se encuentra.

    Para representar esta matriz de páginas, utilizaremos la v-fordirectiva. Para estructuras de datos más complejas, se recomienda proporcionar un keycon each v-for. Vue utiliza el keyvalor para encontrar qué elemento necesita actualizarse, cuando no se proporciona este valor, Vue utiliza una estrategia de “parche local”. Aunque los datos que estamos utilizando son bastante simples, proporcionemos el keyvalor: si utiliza eslint-vue-plugincon las vue3-essentialreglas, siempre deberá proporcionar el keyvalor.

    Revise el Pagination.vuearchivo y startPage()agregue pages():

    src/componentes/Paginación.vue

    template  ul    ...    !-- Visible Buttons Start --    li      v-for="page in pages"      :key="page.name"          button        type="button"        :disabled="page.isDisabled"              {{ page.name }}      /button    /li    !-- Visible Buttons End --    ...  /ul/templatescriptexport 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 inbetween      return this.currentPage - 1;    },    pages() {      const range = [];      for (        let i = this.startPage;        i = Math.min(this.startPage + this.maxVisibleButtons - 1, this.totalPages);        i++      ) {        range.push({          name: i,          isDisabled: i === this.currentPage        });      }      return range;    },  }};/script

    Ahora la lógica para el máximo de botones visibles está terminada.

    Paso 2: agregar detectores de eventos

    Ahora necesitamos informar al componente principal cuando el usuario hace clic en un botón y en qué botón ha hecho clic.

    Necesitamos agregar un detector de eventos a cada uno de nuestros botones. La v-ondirectiva permite detectar eventos DOM. En este ejemplo, usaremos la v-onabreviatura para detectar el evento de clic.

    Para informar al padre, usaremos el $emitmétodo para emitir un evento con la página en la que se hizo clic.

    También nos aseguraremos de que los botones de paginación solo estén activos si la página está disponible. Para ello, utilizaremos para v-bindvincular el valor del disabledatributo con la página actual. También utilizaremos la :abreviatura parav-bind.

    Para mantener nuestra plantilla más limpia, usaremos las propiedades calculadas para verificar si el botón debe estar deshabilitado. El uso de propiedades calculadas también almacenará en caché los valores, lo que significa que, siempre que currentPageno cambien, otras solicitudes para la misma propiedad calculada devolverán el resultado calculado anteriormente sin tener que ejecutar la función nuevamente.

    Revise el Pagination.vuearchivo y agregue comprobaciones para la página actual y haga clic en los métodos de evento:

    src/componentes/Paginación.vue

    template  ul    li      button        type="button"        @click="onClickFirstPage"        :disabled="isInFirstPage"              First      /button    /li    li      button        type="button"        @click="onClickPreviousPage"        :disabled="isInFirstPage"              Previous      /button    /li    !-- Visible Buttons Start --    li      v-for="page in pages"      :key="page.name"          button        type="button"        @click="onClickPage(page.name)"        :disabled="page.isDisabled"              {{ page.name }}      /button    /li    !-- Visible Buttons End --    li      button        type="button"        @click="onClickNextPage"        :disabled="isInLastPage"              Next      /button    /li    li      button        type="button"        @click="onClickLastPage"        :disabled="isInLastPage"              Last      /button    /li  /ul/templatescriptexport 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);    }  }}/script

    Ahora la lógica para hacer clic en los botones está terminada.

    Paso 3: Agregar estilos

    Ahora que nuestro componente verifica todas las funcionalidades que queríamos inicialmente, necesitamos agregar algo de CSS para que se parezca más a un componente de paginación y menos a una lista.

    También queremos que nuestros usuarios puedan identificar claramente en qué página se encuentran. Vamos a cambiar el color del botón que representa la página actual.

    Para ello, podemos vincular un código HTML classa nuestro botón de página activa mediante la sintaxis de objeto . Al utilizar la sintaxis de objeto para vincular nombres de clase, Vue alternará automáticamente la clase cuando cambie el valor.

    Aunque cada bloque dentro de a v-fortiene acceso a las propiedades del ámbito principal, usaremos a methodpara verificar si la página está activa para mantener nuestra plantilla más limpia.

    Revise el pagination.vuearchivo y agregue comprobaciones para la página activa y los estilos y clases CSS:

    src/componentes/Paginación.vue

    template  ul class="pagination"    li class="pagination-item"      button        type="button"        @click="onClickFirstPage"        :disabled="isInFirstPage"              First      /button    /li    li class="pagination-item"      button        type="button"        @click="onClickPreviousPage"        :disabled="isInFirstPage"              Previous      /button    /li    !-- Visible Buttons Start --    li      v-for="page in pages"      class="pagination-item"          button        type="button"        @click="onClickPage(page.name)"        :disabled="page.isDisabled"        :class="{ active: isPageActive(page.name) }"              {{ page.name }}      /button    /li    !-- Visible Buttons End --    li class="pagination-item"      button        type="button"        @click="onClickNextPage"        :disabled="isInLastPage"              Next      /button    /li    li class="pagination-item"      button        type="button"        @click="onClickLastPage"        :disabled="isInLastPage"              Last      /button    /li  /ul/templatescriptexport default {  ...  methods: {    ...    isPageActive(page) {      return this.currentPage === page;    }  }}/scriptstyle.pagination {  list-style-type: none;}.pagination-item {  display: inline-block;}.active {  background-color: #4AAE9B;  color: #ffffff;}/style

    Ahora la lógica para diseñar botones activos está terminada.

    Paso 4: Uso del componente

    En este punto, puedes usar el componente en tu aplicación. Deberás simular una llamada a la API proporcionando valores para totalPagesy perPage.

    Para este ejemplo, currentPagese debe configurar en 1y onPageChangecerrará la sesión de la página activa.

    origen/App.vue

    template  div    pagination      :totalPages="10"      :perPage="10"      :currentPage="currentPage"      @pagechanged="onPageChange"    /  /div/templatescriptimport Pagination from './components/Pagination.vue'export default {  name: 'App',  components: {    Pagination  },  data () {    return {      currentPage: 1,    };  },  methods: {    onPageChange(page) {      console.log(page)      this.currentPage = page;    }  }}/script

    En este punto, puedes ejecutar la aplicación:

    1. npm run serve

    Abra la aplicación en un navegador y observe el componente de paginación. Habrá un botón Primero , Anterior , Siguiente y Último . También se mostrarán tres botones de página de las 10 páginas en total. Dado que la primera página es la página actual, el botón 1 se indica con una clase activa. Además, dado que la primera página es la página actual, los botones Primero y Anterior están deshabilitados.

    Un ejemplo de código en vivo está disponible en CodePen .

    Conclusión

    En este artículo, aprendió cómo crear un componente de paginación Vue.js dinámico y reutilizable.

    Si desea obtener más información sobre Vue.js, consulte nuestra página de temas de Vue.js para obtener ejercicios y proyectos de programación.

    SUSCRÍBETE A NUESTRO BOLETÍN 
    No te pierdas de nuestro contenido ni de ninguna de nuestras guías para que puedas avanzar en los juegos que más te gustan.

    Deja una respuesta

    Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

    Subir

    Este sitio web utiliza cookies para mejorar tu experiencia mientras navegas por él. Este sitio web utiliza cookies para mejorar tu experiencia de usuario. Al continuar navegando, aceptas su uso. Mas informacion