Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
102 views
in Technique[技术] by (71.8m points)

javascript - Vue firebase query: how to show the next results using infinite loading?

I am creating the food order system. I am building the order history page and try to achieve the infinite loading.

I want to show the next five results each time when I press the "next" button.

The each five results must be returned in descending order. The column name is created_at.

The issue now is, if I press the next button once, I can see the sixth to tenth results.

But if I press the button again, I see the sixth to tenth results.

And the same thing is happening again and again, each time I press the next button.

I think I need to use the for loop in my method. But I could not see how to solve this issue.

I am using firebase query in my methods.

My code:

<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>

The collection name is OrdersUser and I am pushing the data to the array named history.

And then, I'm showing the results in the template section using the for loop.

question from:https://stackoverflow.com/questions/65881019/vue-firebase-query-how-to-show-the-next-results-using-infinite-loading

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

You are not setting the last visible document outside your nextPage function, so that function is always starting the query after the 5 initial documents, what you need to do is:

  1. Add a variable that stores the last visible document while you are first populating your list, as below:

    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. Use the lastVisible variable set at the initial load to start you subsequent query, like the following:

    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. Declare the lastVisible variable to your data(), as this will make it accessible both in nextPage() and in mounted() by using this., so like the following:

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...