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

Introducció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, npm
v7.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/cli
para crear un nuevo proyecto Vue:
- npx @vue/cli create --default vue-pagination-example
Luego navegue hasta el directorio del proyecto recién creado;
- cd vue-pagination-example
Crea un Pagination.vue
archivo 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 for
bucle.
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:
- Cuando la página actual es la primera, mostramos al usuario la actual y las siguientes.
- Cuando la página actual sea la última, mostramos la última página y las anteriores.
- 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-for
directiva. Para estructuras de datos más complejas, se recomienda proporcionar un key
con each v-for
. Vue utiliza el key
valor 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 key
valor: si utiliza eslint-vue-plugin
con las vue3-essential
reglas, siempre deberá proporcionar el key
valor.
Revise el Pagination.vue
archivo 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-on
directiva permite detectar eventos DOM. En este ejemplo, usaremos la v-on
abreviatura para detectar el evento de clic.
Para informar al padre, usaremos el $emit
mé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-bind
vincular el valor del disabled
atributo 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 currentPage
no 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.vue
archivo 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 class
a 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-for
tiene acceso a las propiedades del ámbito principal, usaremos a method
para verificar si la página está activa para mantener nuestra plantilla más limpia.
Revise el pagination.vue
archivo 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 totalPages
y perPage
.
Para este ejemplo, currentPage
se debe configurar en 1
y onPageChange
cerrará 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:
- 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.
Deja una respuesta