En este tutorial veremos cómo migrar las funciones de paginación integradas de Laravel a un componente de paginador Vue completo que usa Bootstrap para diseñar. A lo largo del camino, presentaremos algunos conceptos nuevos como aprovechar el enlace del ciclo de vida creado () y configurar un reloj: enlace del ciclo de vida. Nuestro nuevo paginador será un componente secundario del componente Replies.vue, por lo que también necesitaremos establecer mucha comunicación entre estos componentes mediante accesorios, eventos y detectores de eventos. Vayamos ahora a crear un nuevo Vue Paginator.


Paginator utiliza Ajax

En la forma estándar de Laravel de hacer las cosas, es ridículamente fácil configurar la paginación vueTodo lo que tenemos que hacer es renderizar una vista de hoja y pasar a través de una instancia del paginador usando código como lo vemos aquí.

Sin embargo, resulta que threads / show.blade.php ni siquiera usa esto ya que creamos nuestro componente <replies> para usar. Entonces, tal como está ahora, el fragmento a continuación espera recibir la recopilación de respuestas en el enlace de datos que puede utilizar desde allí.

En lugar de esto, haremos que el componente <replies> obtenga sus propios datos según sea necesario mediante una llamada ajax. Así que eliminaremos ese enlace de datos como tal.

Con el enlace de datos en la plantilla eliminado, este medio también props: ['data']se puede eliminar de Replies.vue. Para empezar, eso significa que podemos configurar elementos como una matriz vacía en los datos () de Replies.vue.


El gancho creado ()

Ahora que los datos de las respuestas ya no se pasan al componente, debemos hacer que ese componente sea responsable de obtener sus propios datos por sí solo. Para hacer esto, podemos usar el gancho created () en Vue. Casi funciona como un constructor en el sentido de que cualquier cosa en él se ejecuta inmediatamente después de la creación. En este caso, queremos quecomponente para realizar una llamada ajax para obtener los datos que necesita cuando se crea. Esto podría apagarse así.

Lo que indica el código resaltado es que cuando se crea este componente, realice una solicitud ajax de los datos que necesita. Cuando termine, actualice los datos dentro de este componente.


El punto final de la API de Laravel

Ok, entonces el componente va a realizar solicitudes ajax de los datos que necesita. Primero necesitamos una ruta.

Ahora necesitamos un método index () en el RepliesController. También actualizaremos el middleware de autenticación para que sea menos restrictivo para la API. Ese pequeño método index () está haciendo uso de paginate () pero estamos paginando en cada elemento para que sea muy obvio cuando estamos construyendo el componente para ver cómo funciona.


Configurar la URL en Vue

En Replies.vue, podemos agregar un método url () para averiguar cuál será el punto final al que enviar la solicitud ajax. Vamos a hacer uso de location.pathname en JavaScript para ayudar con esto. Ahora, el método fetch () se apoya en el método url () para devolver el punto final que queremos. En el método refresh (), simplemente desconectaremos los datos que obtenemos de nuestro nuevo punto final para ver dónde estamos.

Ahora, visitemos una página de hilo que sabemos que tiene algunas respuestas. En nuestro caso es http://forum.io/threads/quo/53. Tenga en cuenta que estamos recibiendo una respuesta del servidor y que necesitamos profundizar en el objeto de datos para ver los datos que queremos.
console-log-ajax-response

Este es un buen caso para la Desestructuración de Objetos ES6Si actualizamos el método refresh (), obtenemos acceso a los datos de inmediato sin necesidad de profundizar.

desestructuración de respuesta ajax

Sin embargo, incluso con esta desestructuración, todavía tendremos que profundizar un poco para ver los datos relevantes para el conjunto paginado actualmente. ¿Tener sentido?
conjunto paginado


Guardar los datos de respuesta de Ajax

En realidad, hay dos conjuntos de datos que nos interesan aquí. El primero son los datos sobre el conjunto paginado. ¿Qué página somos, cuál es la página actual, etc.? El siguiente conjunto de datos que necesitamos son las respuestas en sí mismas para que podamos representarlas en el componente. La dataSetvariable representará el primero y la itemsvariable representará el segundo. Así que modificamos el método refresh () para dejar de registrar la respuesta en la consola, y ahora en realidad rellenamos el componente con la información que necesita en la sección data ().

En este punto, los datos de respuesta del servidor se están utilizando para completar el componente de modo que pueda usar esos datos para representar en la página. Aquí, vemos los datos contenidos en el componente <Replies>. Además, el componente en sí también se está renderizando ahora en la página. ¡Muy genial!


Limpieza de un componente de Vue con un Mixin

Los mixins pueden considerarse como fragmentos de código reutilizables que se pueden importar según sea necesario en un archivo determinado. Funcionan de manera similar a como lo hace un Trait en PHP. De hecho, podemos limpiar un poco nuestro componente Replies.vue haciendo uso de un mixin. Primero crearemos un directorio para almacenar nuestros mixins y agregaremos un archivo Collection.js.
directorio de almacenamiento de mixins

El mixin Collection.js ahora tiene este código de secuencia de comandos.

Ahora se puede limpiar el archivo Replies.vue. Sin embargo, tenga en cuenta que ahora debemos importar la colección y actualizar la instancia de Vue para reflejar eso.

Todo sigue funcionando, pero el refactor limpia un poco las cosas, lo cual es bueno.


¡Mirad! El componente <paginator> Vue

Es hora de crear el componente Paginator.vue que hará la paginación por nosotros. Creemos el nuevo archivo y registremos el componente globalmente para que pueda reutilizarse fácilmente en cualquier lugar que deseemos.
nuevo archivo paginator vue

app.js

Ahora podemos desarrollar el esqueleto inicial de la plantilla Paginator.vue.

Realmente vamos a renderizar el desde el componente Replies.vue. Así que agreguemos este marcado así a Replies.vue también.

Esto es suficiente para comenzar a renderizar algo en la página. Aún no es funcional, pero es un buen comienzo.
renderizado del paginador


Cuándo mostrar enlaces de paginación

El componente del paginador debe determinar de manera inteligente si se debe mostrar un enlace anterior o siguiente en función de cuántos elementos hay en la recopilación de datos que se mostrarán en la página. Podemos lograr esto usando v-if y v-show, junto con algunas propiedades de datos que podemos utilizar. Esos serán shouldPaginateprevUrlnextUrlPrimero que nada, recordamos que el componente <replies> es el que está haciendo la llamada ajax real a la API para obtener dos cosas. Obtiene el dataSet, que es una especie de metainformación sobre el paginador y los elementos, que son las propias respuestas. Bueno, el componente <paginator> debe conocer el conjunto de datos. Esto significa que tenemos que vincular dataSet en Replies.vue así.

Por lo tanto, ahora podemos aceptar que los datos del componente secundario <paginator> usan props: ['dataSet']En el fragmento de abajo, el primer v-if determina si el paginador debe mostrarse uniformemente, el primer v-show determina si se debe mostrar el enlace Anterior, el segundo v-show determina si se debe mostrar el enlace Siguiente. En el área de la secuencia de comandos, ahora vemos que dataSet prop en su lugar para aceptar los datos de paginación del componente <replies>. En la sección de datos tenemos configuradas las variables page, prevUrl y nextUrl. Finalmente tenemos la propiedad calculada que debería devolver verdadero o falso y esto determina si el paginador se muestra en absoluto.

Cargarlo en el navegador e inspeccionarlo en las herramientas de desarrollo de Vue nos muestra que, de hecho, está obteniendo los datos que necesita del componente principal. Sin embargo, existe un pequeño problema. Parece que shouldPaginate ahora es falso, cuando en realidad debería ser cierto ya que hay un next_page_url disponible.
carga de datos del paginador a través de prop


Presentando el objeto de reloj

Podemos usar esta característica de VueJS para observar la propiedad dataSet. Ahora, si esa propiedad cambia alguna vez, entonces los datos deberían actualizarse en el componente instantáneamente. Si agrega este objeto a la sección de script de Paginator.vue, esto es exactamente lo que logramos.

Las herramientas de desarrollo de Vue ahora muestran que el conjunto de datos ahora tiene un valor real para shouldPaginate.
ejemplo de objeto de reloj de vuejs


Asignar controladores de clics a enlaces paginados

Algo debe suceder cuando un usuario hace clic en los enlaces Siguiente o Anterior en el paginador. Que queremos que pase. Bueno, si hace clic en el enlace Anterior, la pagevariable debería reducirse en 1. Si hace clic en el enlace Siguiente, la pagevariable debería aumentar en 1. Esta es una edición simple de Paginator.vue en el área de la plantilla como tal.

Con esto en su lugar, podemos hacer clic en el enlace Siguiente y luego verlo actualizar en las herramientas de desarrollo de Vue. ¡Muy genial!
vuejs haga clic y luego incremente


Emitiendo un evento del niño

Cuando un usuario hace clic en uno de esos enlaces, indica que el usuario quiere una nueva página. Eso significa que debe ocurrir una llamada ajax. Una buena manera de abordar esto es agregar esa pagepropiedad al observador y disparar un evento si alguna vez cambia. Entonces, lo que vemos a continuación es básicamente decir, si esa variable de página alguna vez cambia, ejecute el método broadcast () que emitirá un evento llamado 'cambiado' y pasará por la página que el usuario está solicitando.

Ok, se disparó un evento, ¿ahora qué? Bueno, podemos escuchar ese evento dentro del componente <replies> donde se hace referencia al <paginator> así. Esto dice que cuando ocurra el evento 'cambiado', active el método fetch () para obtener nuevos datos del servidor.


Ciclo de vida de la paginación

Muy rápido, hagamos un resumen del ciclo de vida de la paginación.


1. La página se carga por primera vez y el Paginador muestra un enlace Siguiente.

Paginator muestra un enlace Siguiente


2. El usuario hace clic en el enlace y la pagevariable se incrementa en uno en Paginator.vue.

incrementado en uno en Paginator


3. Esa pagepropiedad está siendo observada, por lo que el método de transmisión se activa emitiendo un evento 'cambiado' mientras pasa el número de página solicitado.

incendios del método de difusión


4. Dentro del componente <replies>, se configura un oyente @changed. Cuando escucha ese evento emitido, activa la llamada ajax fetch ().

escuchar el cambio de evento


5. Cuando se completa la llamada ajax, las variables dataSetitemsse actualizan mediante el método refresh () en Replies.vue.

buscar y luego actualizar


6. La dataSetvariable en Replies.vue está vinculada al <paginator>. Por lo tanto, la actualización dataSetcae en cascada hasta el componente Paginator.vue.

enlace de datos en el componente principal


7. El componente Paginator.vue acepta eso a dataSettravés de un prop.

aceptar datos a través de prop


8. El componente Paginator.vue también tiene un reloj que estaba apoyada en dataSet, por lo que lo actualiza las propias pageprevUrlnextUrllas variables.

reloj configurado en conjunto de datos


9. Por lo tanto, tanto las respuestas enumeradas en <respuestas> como los enlaces de paginación en <paginador> se actualizan en tiempo real a medida que se hace clic en ellos.

actualización de la paginación en tiempo real a medida que se hace clic en ellos

Paginator.vue

Replies.vue


Actualización de direcciones URL y estado de inserción

URL que maneja el paginador
El paginador en sí es ahora completamente funcional, sin embargo, si visita una URL en el navegador como http://forum.io/threads/quo/53?page=2, por ejemplo, no está manejando el paginador correctamente . La URL dice que deberíamos estar en la página 2 de los resultados paginados, pero la página 1 todavía se muestra. Podemos actualizar el método url () dentro de Replies.vue para usar este fragmento de código.

Todo lo que sucede aquí es que, si no hay ningún valor para la variable de página, entonces podemos usar location.search para inspeccionar la parte de la cadena de consulta de la URL en el navegador. Por lo tanto, usar location.search cuando la URL es http://forum.io/threads/quo/53?page=2 devolvería “? Page = 2”. Luego, debemos aplicar una expresión regular para reducir el resultado al valor de página numérico que necesitamos. Con esta adición, la URL ahora está manejando el paginador correctamente.

Paginator manejando la URL
Ahora necesitamos hacer esto al revés. Ahora mismo, hacer clic en los enlaces en el paginador nos mueve correctamente hacia adelante y hacia atrás dentro del conjunto paginado. Sin embargo, la URL del navegador no se actualiza. Simplemente permanece igual a medida que hace clic hacia adelante y hacia atrás. Esto se puede solucionar con el método history.pushState () en JavaScriptSi agregamos un método al componente Paginator.vue de esa manera, debería habilitar esta función.


El código final de Paginator

Este tutorial utilizó un componente Paginator.vue dedicado junto con un componente principal Replies.vue. Nos dio una buena oportunidad para construir la funcionalidad de paginación desde cero y nos ayudará a comprender completamente cómo funciona la paginación en VueJS con el estilo Bootstrap y Laravel proporcionando los datos a través de su API. Los dos archivos finales se ven así.

Paginator.vue

Replies.vue


Resumen del componente de paginación Bootstrap de VueJS

ejemplo de paginador de trabajo final
Ahora podemos ver que todo está funcionando muy bien. Aquí cargamos un hilo con un montón de respuestas en la primera página. Luego vamos a la quinta página en la barra de URL y cargamos manualmente esa página. El conjunto paginado carga correctamente las respuestas para esa página. Luego, hacemos lo contrario. Empezamos haciendo clic en los enlaces en el paginador, vemos que la página cambia correctamente, y ahora también vemos la URL actualizándose correctamente gracias a hacer uso de la función history.pushState ().