【问题标题】:Vue firebase query: how to show the next results using infinite loading?Vue firebase查询:如何使用无限加载显示下一个结果?
【发布时间】:2021-04-29 00:53:25
【问题描述】:

我正在创建食品订购系统。我正在构建订单历史页面,并尝试实现无限加载。

我想在每次按下“下一步”按钮时显示接下来的五个结果。

每五个结果必须按降序返回。列名是created_at

现在的问题是,如果我按一次下一步按钮,我可以看到第六到第十个结果。

但如果我再次按下按钮,我会看到第六到第十个结果。

同样的事情一次又一次地发生,每次我按下下一个按钮。

我想我需要在我的方法中使用 for 循环。但我看不出如何解决这个问题。

我在我的方法中使用 firebase 查询。

我的代码:

<template>
    <div>
        <NavbarMobile />
        <CartSmartphone class="mb-5" />
        <b-container class="history-mobile">
            <b-row class="mb-2 orders">
                <span class="ml-2 orders">Your orders</span>
            </b-row>
            <div class="user-section d-flex " v-for="(item, index) in history" :key="index">
                <div v-if="item.status == 'processing'" class="card-area">
                    <div class=" mb-3" v-for="(sample, index) in item.sample" :key="index">
                        <router-link :to="{name:'OrderSmartphone',params:{id: item.code}}">
                            <b-card :img-src="sample" img-alt="Card image" img-left class="mb-3">
                                <b-card-text class="text">
                                    <!-- Some quick example text to build on the card and make up the bulk of the card's content. -->
                                    <ul class="list-unstyled">
                                        <b-row tag="li">
                                        <span class="shop">{{ item.business }}</span>
                                        </b-row>
                                        <div cols="12" class="d-flex my-3">
                                            <span  class="date">{{ item.day }}/{{ item.month }}/{{ item.year}}</span>
                                            <span  class="status">{{ item.status }}</span>
                                        </div>
                                        <b-row class="my-3">
                                            <span class="price">{{ item.sale }}</span>
                                        </b-row>
                                    </ul>
                                
                                </b-card-text>
                            </b-card>
                        </router-link>
                    </div>
                </div>
                <div v-else class="card-area">
                    <div class="card-area mb-3" v-for="(sample, index) in item.sample" :key="index">
                   
                        <b-card :img-src="sample" img-alt="Card image" img-left class="mb-3">
                            <b-card-text class="text">
                                <!-- Some quick example text to build on the card and make up the bulk of the card's content. -->
                                <ul class="list-unstyled">
                                    <b-row tag="li">
                                    <span class="shop">{{ item.business }}</span>
                                    </b-row>
                                    <div cols="12" class="d-flex my-3">
                                        <span  class="date">{{ item.day }}/{{ item.month }}/{{ item.year}}</span>
                                        <span  class="status">{{ item.status }}</span>
                                    </div>
                                    <b-row class="my-3">
                                        <span class="price">{{ item.sale }}</span>
                                    </b-row>
                                </ul>
                            
                            </b-card-text>
                        </b-card>
                   
                </div>
                </div>
                
                <div class="arrow-area">
                    <div class="svg">
                         <svg xmlns="http://www.w3.org/2000/svg" width="5.126" height="9.313" viewBox="0 0 5.126 9.313">
                            <g id="download" transform="translate(-116.995 9.036) rotate(-90)">
                                <path id="パス_390" data-name="パス 390" d="M8.452,117.33,4.4,121.385.344,117.33a.19.19,0,0,0-.269.269l4.189,4.189a.19.19,0,0,0,.269,0L8.722,117.6a.19.19,0,0,0-.265-.274l0,0Z" transform="translate(-0.021 0)" fill="#fff" stroke="#fff" stroke-width="0.5"/>
                                <path id="パス_391" data-name="パス 391" d="M4.377,121.845a.19.19,0,0,1-.135-.056L.053,117.6a.19.19,0,0,1,.269-.269l4.055,4.054,4.054-4.055a.19.19,0,0,1,.274.265l0,0-4.189,4.189A.19.19,0,0,1,4.377,121.845Z" transform="translate(0 -0.001)" fill="#fff" stroke="#fff" stroke-width="0.5"/>
                            </g>
                        </svg>
                    </div>
                </div>
            </div>
        </b-container>
        <b-button @click.prevent="nextPage" class="next">next</b-button>
         <FooterMobile />
    </div>
</template>

<script>
import CartSmartphone from "@/mobile/CartSmartphone.vue";
import NavbarMobile from "@/components/NavbarMobile.vue";
import FooterMobile from "@/sections/FooterMobile.vue";
import fireApp from '@/plugins/firebase'
const firebase = require("firebase");
require("firebase/firestore");
const db = firebase.firestore();


    export default {
        name: 'UserSmartphone',
        components: {
            CartSmartphone,
            NavbarMobile,
            FooterMobile
        },
        data() {
            return {
                customer: this.$route.params.id,
                history: [],
                sample: ""
            }
        },
        mounted() {
            // const customerId = this.$route.params.id
            // this.customer = customerId

            

            const dbOrdersRef = db.collection('OrdersUser').doc(this.$route.params.id).collection('Orders').orderBy("created_at", "desc").limit(5)
            dbOrdersRef.onSnapshot((querySnapshot) => {
                querySnapshot.forEach((doc) => {
                    
                    const historyData = doc.data()
                    this.history.push(historyData)
                    
                    this.sample = doc.data().sample

        
                })
            })
        },
        methods: {
            nextPage() {
                fireApp.auth().onAuthStateChanged((user) => {
                if (user) {
                    const userId = fireApp.auth().currentUser.uid;

                    
                    const first = db.collection('OrdersUser').doc(userId).collection('Orders').orderBy("created_at", "desc").limit(5)
                    
                    return first.onSnapshot((querySnapshot) => {
                    // Construct a new query starting at this document,
                    // get the next 5 results.
                        var lastVisible = querySnapshot.docs[querySnapshot.docs.length - 1];
                        console.log("last", lastVisible);

                        var next = db.collection('OrdersUser').doc(userId).collection('Orders').orderBy("created_at", "desc")
                                    .startAfter(lastVisible)
                                    .limit(5);

                        next.onSnapshot((nextQuery) => {
                            nextQuery.forEach((doc) => {
                                
                                const nextData = doc.data()
                                console.log(nextData)
                                this.history.push(nextData)
                            })
                        })
                    });
                } 
            })
            },
        }
    }
</script>

集合名称是OrdersUser,我将数据推送到名为history的数组中。

然后,我使用 for 循环在模板部分显示结果。

【问题讨论】:

    标签: javascript firebase vue.js for-loop google-cloud-firestore


    【解决方案1】:

    您没有在 nextPage 函数之外设置最后一个可见文档,因此该函数始终在 5 个初始文档之后开始查询,您需要做的是:

    1. 在您第一次填充列表时添加一个变量来存储最后一个可见文档,如下所示:

      const dbOrdersRef = db.collection('OrdersUser').doc(this.$route.params.id)
                            .collection('Orders').orderBy("created_at", "desc").limit(5);
      dbOrdersRef.onSnapshot((querySnapshot) => {
          querySnapshot.forEach((doc) => {
              const historyData = doc.data()
              this.history.push(historyData)
              this.sample = doc.data().sample
          })
          this.lastVisible = querySnapshot.docs[querySnapshot.docs.length-1];
      })
      
    2. 使用在初始加载时设置的lastVisible 变量来启动后续查询,如下所示:

      nextPage() {
           fireApp.auth().onAuthStateChanged((user) => {
               if (user) {
                   const userId = fireApp.auth().currentUser.uid;
                   const next = db.collection('OrdersUser')
                                  .doc(userId)
                                  .collection('Orders')
                                  .orderBy("created_at", "desc")
                                  .startAfter(this.lastVisible)
                                  .limit(5);
      
                   return next.onSnapshot((nextQuery) => {
                       nextQuery.forEach((doc) => {
                           const nextData = doc.data()
                           console.log(nextData)
                           this.history.push(nextData)
                       })
                       this.lastVisible = nextQuery.docs[nextQuery.docs.length-1];
                   })
      
               };
      
           }) 
      }
      
    1. lastVisible 变量声明为您的data(),因为这将使其在nextPage()mounted() 中都可以使用this. 访问,如下所示:

      data() {
           return {
               customer: this.$route.params.id,
               history: [],
               sample: "",
               lastVisible: ""
           }
       },
      

    【讨论】:

    • 感谢您的帮助,但我收到错误“未定义 lastVisible”。我在安装部分使用了您的第一个代码,然后在方法部分使用了第二个代码。实际上,“var lastVisible;”是什么意思?在你的第一个代码中是什么意思?
    • 它基本上是你最初设置的最后一个文件,所以你需要在startAt上使用你的后续文件集,你可以查看this documentation了解更多详细信息,我会检查什么是我分享的代码有问题并尽快更新答案。
    • 我用另一个步骤编辑了这个问题来修复它,检查一下。还稍微更改了第 1 步和第 2 步。
    猜你喜欢
    • 1970-01-01
    • 2021-02-24
    • 1970-01-01
    • 1970-01-01
    • 2017-08-11
    • 2015-12-18
    • 2019-04-17
    • 2020-12-04
    • 2014-08-14
    相关资源
    最近更新 更多