首页 > 解决方案 > 使用 Vue 进行 Firestore 分页

问题描述

使用 bootstrap-vue 分页组件:

<b-pagination
  v-model="currentPage"
  :total-rows="rows"
  :per-page="perPage"
></b-pagination>

组件.vue:

export default class Links extends Vue {
  public currentPage: number = 1
  public perPage: number = 20
  public rows: number = 1

  @Watch('currentPage')
  onCurrentPageChange(page: number) {
    const startAt = page * this.perPage - this.perPage
    db.collection('links')
      .orderBy('created', 'desc')
      .startAt(startAt)
      .limit(this.perPage)
      .get()
      .then(snap => {
        console.log(snap.docs)
      })
  }
}

currentPage值更改时,我会获取新的数据库值,startAt但它什么也不返回。我的 Firestore 有以下文档的字段:

如何使用偏移量/限制进行正常分页?

标签: javascriptvue.jsgoogle-cloud-firestore

解决方案


我也有类似的分页问题。文档似乎不够,即它们向您展示了如何转到下一页,但没有告诉您如何返回上一页。真是令人沮丧。

下面是我如何实现一个简单的分页。我已经配置好了,VueFire我 会直接上代码。FirebaseBootstrapVue

没有人向您展示的不同之处。

  • 使用VueFire编程绑定而不是声明性绑定,请参见此处
  • firstVisible项目firebase运行documentSnapshots.docs[0]
<template>
    <div>
        <p>{{countries}}</p>
         <b-button-group size="lg" class="mx-2">
      <b-button :disabled="prev_btn" @click="previous" >&laquo;</b-button>
      <b-button :disabled="next_btn" @click="next">&raquo;</b-button>
    </b-button-group>
    </div>
</template>
<script>
 import firebase from 'firebase/app'
import 'firebase/auth'
import { db } from '../main'

export default {
 name: 'Countries',
 data () {
  return {
   countries: [],
   limit: 2,
   lastVisible: '',
   firstVisible: '',
   next_btn: false,
   prev_btn: true
  }
 },
 methods: {
  next () {
   if (!this.next_btn) {
   // bind data with countries
    this.$bind('countries', db.collection('Countries').orderBy('createdAt').startAfter(this.lastVisible).limit(this.limit))
    // set last and first visible items
    db.collection('Countries').orderBy('createdAt').startAfter(this.lastVisible).limit(this.limit).get().then(documentSnapshots => {
     this.lastVisible = documentSnapshots.docs[documentSnapshots.docs.length - 1]
     this.firstVisible = documentSnapshots.docs[0]
    }).then(() => {
     // Peep  on the next  next query to see if it gives zero
     db.collection('Countries').orderBy('createdAt').startAfter(this.lastVisible).limit(this.limit).get()
      .then(snap => {
       if (snap.size === 0) {
        //disable button if the next peeped result gets zero
        this.next_btn = true
        // enable previous button
        this.prev_btn = false
       } else {
        // enable next button if peeped result is not zero
        this.next_btn = false
        // enable previous button
        this.prev_btn = false
       }
      })
    })
   }
  },
  previous () {
   // Ensure previous is not zero
   db.collection('Countries').orderBy('createdAt').endBefore(this.firstVisible).limitToLast(this.limit).get().then(snap => { return snap.size })
   .then(size => {
    //confirm is not zero here
    if (size !== 0) {
     //bind the previous to countries
     this.$bind('countries', db.collection('Countries').orderBy('createdAt').endBefore(this.firstVisible).limitToLast(this.limit))
     // Set last and first visible
     db.collection('Countries').orderBy('createdAt').endBefore(this.firstVisible).limitToLast(this.limit).get().then(documentSnapshots => {
      this.lastVisible = documentSnapshots.docs[documentSnapshots.docs.length - 1]
      this.firstVisible = documentSnapshots.docs[0]
     }).then(() => {
      // peep the next previous query
      db.collection('Countries').orderBy('createdAt').endBefore(this.firstVisible).limitToLast(this.limit).get()
       .then(snap => {
        if (snap.size === 0) {
         //if next peeped previous button gets 0 disable
         this.prev_btn = true
         this.next_btn = false
        } else {
         //if next peeped result is does not get 0 enable buttons
         this.prev_btn = false
         this.next_btn = false
        }
       })
     })
    }
   })
  }
 },
 mounted () {
  // run first query and bind data
  this.$bind('countries', db.collection('Countries').orderBy('createdAt').limit(this.limit))
  // set last and first Visible
  db.collection('Countries').orderBy('createdAt').limit(this.limit).get().then(documentSnapshots => {
   this.lastVisible = documentSnapshots.docs[documentSnapshots.docs.length - 1]
   this.firstVisible = documentSnapshots.docs[0]
  }).then(() => {
            // peep to check if next should be on or off
            db.collection('Countries').orderBy('createdAt').startAfter(this.lastVisible).limit(this.limit).get()
                .then(snap => {
                    if (snap.size === 0) {
                        this.next_btn = true
                    }
                })
        })
 }
}
</script>


推荐阅读