Paginar los datos del almacén de incendios al usar vuex y agregar nuevos datos al estado

2020-06-29 javascript vue.js vuex vuexfire

Implementé lo siguiente para mostrar una consulta paginada (esto fue sugerido por Tony O'Hagan en esta publicación: Cómo obtener el último documento de una consulta VueFire ):

bindUsers: firestoreAction(({ bindFirestoreRef }) => {
  return bindFirestoreRef('users', 
      Firebase.firestore().collection('users').limit(8), { serialize })
}),
bindMoreUsers: firestoreAction(context => {
  return context.bindFirestoreRef('users', Firebase.firestore().collection('users').startAfter(context.state.users[context.state.users.length - 1]._doc).limit(8), { serialize })
})

Cuando el usuario se desplaza hasta el final de la página, llamo a bindMoreUsers, que actualiza state.users al siguiente conjunto de 8 documentos. Necesito poder agregar a state.users en lugar de sobrescribir el conjunto original de 8 documentos. ¿Cómo puedo hacer esto?

Answers

Confesión: todavía no he implementado la paginación en mi aplicación actual, pero así es como lo abordaría.

En mi respuesta anterior , expliqué cómo mantener referencias a los objetos de doc Firestore dentro de cada elemento de la matriz de estado que está vinculado por VuexFire o VueFire. En la Solución n. ° 1 a continuación, utilizamos estos objetos doc para implementar la paginación basada en el cursor recomendada por Firestore de los conjuntos de resultados de una consulta utilizando la condición de consulta startAfter(doc) lugar de la cláusula de offset más lenta y costosa.

Tenga en cuenta que, dado que estamos usando Vuexfire / Vuefire, estamos diciendo que deseamos suscribirnos a los cambios en vivo de nuestra consulta, por lo que nuestra consulta enlazada definirá con precisión qué termina en nuestra matriz enlazada.

Solución # 1 . La paginación hacia adelante / hacia atrás carga y muestra una porción horizontal del conjunto de datos completo (nuestra matriz enlazada mantiene el mismo tamaño = tamaño de página). Esto no es lo que solicitó, pero podría ser una solución preferida dados los Cons de otras soluciones.

  • Pros : Servidor: para grandes conjuntos de datos, esta consulta de paginación se ejecutará con el menor costo y retraso.
  • Pros : Cliente: Mantiene una pequeña huella de memoria y se procesará más rápido.
  • Contras : la paginación probablemente no se sentirá como un desplazamiento. La interfaz de usuario probablemente solo tenga botones para avanzar / retroceder.
  • Avance de página : obtenga el objeto doc del último elemento de nuestra matriz de estado y aplique una startAfter(doc) a nuestra consulta de vista actualizada que une nuestra matriz a la página siguiente.
  • Página al revés : ¡Un poco más difícil! Obtenga el objeto doc del primer elemento de nuestra matriz de estado enlazado. Ejecute nuestra consulta de página con startAfter (doc), limit (1), offset (pagesize-1) y orden de clasificación inverso . El resultado es el documento inicial (pageDoc) de la página anterior. Ahora use startAfter(pageDoc) y reenvíe el orden de clasificación y el límite (pageSize) para volver a vincular la matriz de estado (la misma consulta que Page Forward pero con doc = pageDoc).

NOTA: En el caso general, argumentaría que no podemos simplemente mantener los valores de pageDoc de las páginas anteriores (para evitar nuestra consulta inversa) ya que estamos tratando esto como una lista filtrada de actualización 'en vivo' por lo que el número de elementos aún restante de páginas anteriores podría haber cambiado radicalmente desde que nos desplazamos hacia abajo. Es posible que su aplicación específica no espere esta tasa de cambio, por lo que tal vez mantener valores anteriores de pageDoc sería más inteligente.

Solución # 2 . Paginación hacia adelante, extiende el tamaño del resultado de la consulta y la matriz enlazada.

  • Pros : UX se siente como un desplazamiento normal ya que nuestra matriz crece.

  • Pros : no es necesario usar el truco del serializer ya que no estamos usando startAfter() o endBefore()

  • Contras : Servidor: está volviendo a cargar desde Firestore toda la matriz hasta la nueva página cada vez que vuelve a vincular a una nueva página y luego obtiene actualizaciones en vivo para una matriz en crecimiento. ¡Todas esas lecturas de documentos podrían ser caras!

  • Contras : Cliente: el procesamiento puede ser más lento a medida que avanza la página, aunque shadow DOM puede solucionarlo. La interfaz de usuario puede parpadear a medida que la recarga cada vez, por lo que se necesitan más trucos de magia de la interfaz de usuario (retrasar el procesamiento hasta que la matriz esté completamente actualizada).

  • Pros : podría funcionar bien si estamos utilizando una función de desplazamiento infinito . Tendría que probarlo.

  • Reenvío de página : agregue pageSize a nuestro límite de consulta y vuelva a vincular, lo que volverá a consultar Firestore y volverá a cargar todo.

  • Página hacia atrás : reste pageSize de nuestro límite de consulta y vuelva a vincular / recargar (o no). Puede que también necesite actualizar nuestra posición de desplazamiento.

Solución # 3 . Híbrido de la solución n. ° 1 y n. ° 2. Podríamos elegir usar el enlace Vuexfire / Vuefire en vivo para solo una porción de nuestra consulta / colección (como la solución # 1) y usar una función calculada para concatenarlo con una matriz que contiene las páginas de datos que ya hemos cargado.

  • Pros : Reduce el costo de consulta de Firestore y el retraso de la consulta, pero ahora con una apariencia de desplazamiento suave, por lo que puede usar la interfaz de usuario de desplazamiento infinito. ¡Pásame un Koolaid!
  • Contras : tendremos que tratar de hacer un seguimiento de qué parte de nuestra matriz se muestra y hacer que esa parte se limite y se actualice en vivo.
  • Página adelante / atrás: el mismo trato que la Solución n. ° 1 para enlazar la página de datos actual, excepto que ahora tenemos que copiar la página de datos anterior en nuestra matriz de datos no en vivo y codificar una pequeña función calculada para concat() los dos matrices y luego enlazar la lista de UI a esta matriz calculada.

Solución # 3a Podemos hacer trampa y no mantener las páginas de datos anteriores invisibles. En su lugar, simplemente reemplazamos cada página con un div (o similar) de la misma altura;) así que nuestro aspecto de desplazamiento nos hemos desplazado hacia abajo en la misma distancia. A medida que nos desplazamos hacia atrás, tendremos que eliminar nuestro disimulado div página anterior y reemplazarlo con los datos recién vinculados. Si está utilizando el desplazamiento infinito, para que el UX de desplazamiento sea agradable y suave, deberá precargar una página adicional adelante o atrás para que ya esté cargada antes de desplazarse al salto de página. Algunas API de desplazamiento infinito no admiten esto.

Las soluciones n. ° 1 y n. ° 3 probablemente necesiten un PR de Cookbook para VueFire o una buena biblioteca MIT'd / NPM. ¿Ningún arrendatario?

Related