vue.js и запрос firebase, дающий неправильное количество массивов

#javascript #firebase #vue.js

#javascript #firebase #vue.js

Вопрос:

происходит что-то странное. Я использую Vue.js и Firebase. мой запрос прост. У меня есть 3 документа в базе данных

 let tagRef = db.collection('tags')
        tagRef = tagRef.where('gid', '==', this.$store.getters.gid)
        tagRef.onSnapshot(snapshot => {
            this.tags = []
            snapshot.docChanges().forEach(change => {
                let docs = change.doc
                this.tags.push(docs.data())
                console.log(this.tags.length)
            })
        })
  

как вы можете видеть, я записываю длину массива в консоль. когда я обновляю страницу, в журнале моей консоли отображается 1 1 2 однако при внесении изменений читается правильно 1 2 3

Я не уверен, почему он это делает.

Когда я меняю консоль.войдите из this.tags.длина к this.tags прилагаются снимки экрана того, что я получаю.

при обновлении страницы

введите описание изображения здесь

когда происходит изменение

введите описание изображения здесь

любая помощь приветствуется.

Обновить:

Это игра. игроки могут помечать друг друга. когда игрок получает метку, он временно отключается, пока его метка не будет завершена. вторая часть заключается в том, что каждый игрок может быть помечен не более 3 раз.

В обработчике created() я запрашиваю теги, и я использую часть firebase в реальном времени, поэтому всякий раз, когда что-то меняется в базе данных тегов, код обновляется.

У меня есть метод, как показано ниже:

 countTags(team) {
            return this.tags.filter(function (tag) {
                if(tag.tagged == team.team_id){
                    return team
                }
            })
        },
  

Предполагается, что этот метод возвращает теги, основанные на идентификаторе команды. в html у меня есть это

 :class="{'taglimit' : countTags(team).length >= 3}" 
  

который добавит класс «taglimit», если количество равно 3 или больше.

ВТОРОЕ ОБНОВЛЕНИЕ:

Когда я запускаю этот запрос в созданном перехватчике, у меня возникают проблемы

 let tagRef = db.collection('tags')
    tagRef = tagRef.where('gid', '==', this.$store.getters.gid)
    tagRef.onSnapshot(snapshot => {
        this.tags = []
        snapshot.docChanges().forEach(change => {
            let docs = change.doc
            this.tags.push(docs.data())
        })
    })
  

но когда я запускаю этот запрос, я не

 let tagRef = db.collection('tags')
        tagRef = tagRef.where('gid', '==', this.$store.getters.gid)
        tagRef.get().then((snapshot) => {
            snapshot.forEach(doc => {
                let tag = doc.data()
                tag.id = doc.id
                this.tags.push(tag)
            })
        }).catch(err => {
            console.log(err)
        })
  

Проблема в том, что мне нужно обновлять код каждый раз, когда изменяется база данных тегов.

THIRD UPDATE

I think I found the issue. I moved this.tags = [] outside the query and everything appears to be working fine now. so now the query looks like this.

 this.tags = []
let tagRef = db.collection('tags')
    tagRef = tagRef.where('gid', '==', this.$store.getters.gid)
    tagRef.onSnapshot(snapshot => {
        snapshot.docChanges().forEach(change => {
            let docs = change.doc
            this.tags.push(docs.data())
            console.log(this.tags.length)
        })
    })
  

FOURTH UPDATE:

here is the HTML

 <v-dialog v-model="dialog" persistent transition="scale-transition" fullscreen light>
            <v-btn
            slot="activator"
            fixed
            dark
            fab
            bottom
            right
            color="blue-grey darken-2"
            class="pulse-button"
            >
            <v-icon>directions_run</v-icon>
            </v-btn>
            <v-card color="rgba(224, 224, 224, .95)">
                <v-container grid-list-md text-xs-center>
                    <v-layout row wrap class="tagform-container">
                        <v-btn dark fab right absolute small color="grey darken-3"  @click="dialog = false"><v-icon>close</v-icon></v-btn>
                        <v-layout justify-center>
                            <v-card-title class="display-2 font-weight-black">TAG!</v-card-title>
                        </v-layout>
                        <v-card-text class="subheading">Select a team you want to tag. Note, you only have one tag per game. Use it wisely!</v-card-text>
                        <v-flex xs4 class="add-flex" v-for="team in activeTeams" :key="team.id" >
                            <div class="tag-card" 
                                :class="{'disabled' : activeTag(team).length > 0, 'taglimit' : countTags(team).length >= 3}" 
                                height="100%" 
                                color="white" 
                                style="background:#fff;" 
                                @click="activeTag(team).length > 0 || countTags(team).length >= 3 ? '' : selectedTeam(team)"
                                >
                                <v-layout justify-center>
                                    <v-card-title class="title">{{team.team_name}}</v-card-title>
                                </v-layout>
                                <v-responsive>
                                    <img class="avatar" v-bind:src="team.url">
                                </v-responsive>
                                <v-flex>
                                    <v-card-text class="body-2 text-uppercase">Tap to select</v-card-text>
                                </v-flex>
                            </div>
                        </v-flex>
                    </v-layout>
                </v-container>
            </v-card>
        </v-dialog>
  

There is more but this is the part that counts.

Here is some more of the code

 data() {
        return {
            feedback: null,
            teams: [],
            taggedteam: null,
            dialog: false,
            stepper: false,
            emojiinput: '',
            search: '',
            e1: 1,
            tag: null,
            tags: [],
            completedtags: [],
            tagstates: []
        }
    },
computed: {
        activeTeams: function () {
            let thisTeam = this.$store.getters.player.team_id
            return this.teams.filter(function (team) {
                if(team.team_id !== thisTeam)
                    return team
            })
        }
    },
  

Один из методов:

 countTags(team) {
            return this.tags.filter(function (tag) {
                if(tag.tagged == team.team_id){
                    return team
                }
            })
        },
  

наконец, созданный хук

 created(){
        // get teams
        let teamRef = db.collection('teams')
        teamRef = teamRef.where('gid', '==', this.$store.getters.gid)
        teamRef = teamRef.orderBy('team_id')
        teamRef.onSnapshot(snapshot => {
            snapshot.docChanges().forEach(change => {
                if(change.type == 'added') {
                    let docs = change.doc

                    let leaderRef = db.collection('leaderboard')
                    leaderRef = leaderRef.where('gid', '==', this.$store.getters.gid)
                    leaderRef = leaderRef.where('team', '==', docs.data().team_id)
                    leaderRef = leaderRef.where('missioncomplete', '==', true)
                    leaderRef.onSnapshot(snapshot => {
                        if(snapshot.empty) {
                            // team has not completed the mission so they can still be tagged
                            this.teams.push(docs.data())
                        }
                    })

                }
            })
        })

        // get tags
        this.tags = []
        let tagRef = db.collection('tags')
        tagRef = tagRef.where('gid', '==', this.$store.getters.gid)
        tagRef.onSnapshot(snapshot => {
            snapshot.docChanges().forEach(change => {
                let docs = change.doc
                this.tags.push(docs.data())
            })
        })

        // get tag states
        this.tagstates = []
        let tagStateRef = db.collection('tagstate')
        tagStateRef = tagStateRef.where('gid', '==', this.$store.getters.gid)
        tagStateRef = tagStateRef.where('state', '==', true)
        tagStateRef = tagStateRef.orderBy('tag')
        tagStateRef.onSnapshot(snapshot => {
            snapshot.docChanges().forEach(change => {
                let docs = change.doc
                this.tagstates.push(docs.data())
            })
        })

        if(this.$store.getters.player.team_id) {
            // check to see if this player has already tagged someone
            let tagRef = db.collection('tags')
            tagRef = tagRef.where('tagger', '==', this.$store.getters.player.team_id)
            tagRef = tagRef.where('gid', '==', this.$store.getters.gid)
            tagRef.onSnapshot(snapshot => {
                snapshot.docChanges().forEach(change => {
                    let docs = change.doc
                    this.completedtags.push(docs.data())
                })
            })
        }
    }
  

Комментарии:

1. Я пытался воспроизвести вашу проблему, но безуспешно (у меня это хорошо работает). Однако трудно быть уверенным, что я воспроизвел его правильно, поскольку вы не предоставляете доступ к полному коду вашего компонента (в частности, к объекту данных). Я думаю, вам следует инициализировать объект данных tags вне обратного вызова или, что лучше, непосредственно в объекте данных. Если вы поделитесь большей частью своего кода и объясните свою точную цель, мы можем помочь вам лучше.

2. интересно, что я попытался воспроизвести это с помощью своего iPhone и в Safari на своем рабочем столе, но не смог. Я нахожусь на локальном сервере, и, похоже, это происходит только в chrome. Не уверен, почему это так. вы все еще хотели бы увидеть остальную часть кода?

3. Да, конечно! а также объясните, какова ваша функциональная цель с этим слушателем, пожалуйста.

4. Я обновил вопрос дополнительной информацией. Дайте мне знать, если вам нужно больше. Я все еще получаю странные вещи в Chrome, поэтому я знаю, что делаю что-то не так 🙂

5. @RenaudTarnec Я обновляю вопрос во второй раз, добавляя новую информацию

Ответ №1:

Немного сложно погрузиться в ваш код, не зная точной взаимосвязи между командами / тегами и их соответствующими ограничениями.

Но я понял из обсуждения, что вы хотите изменить класс элемента DOM, если результатом запроса является более 3 документов.

Ниже вы найдете возможный подход, который показывает, как управлять изменением класса (а также, при необходимости, как поддерживать tags массив в data объекте, т. Е. реагировать на изменения базы данных).

 <template>
  <div :class="{ taglimit: isTagLimit }">Test</div>
</template>

<script>
const fb = require("../firebaseConfig.js");
export default {
  data() {
    return {
      tags: [],
      isTagLimit: false
    };
  },

  created: function() {
    let tagRef = fb.db.collection("tags");
    tagRef = tagRef.where("gid", "==", this.$store.getters.gid);
    tagRef.onSnapshot(querySnapshot => {
      console.log(querySnapshot.size);
      //The next if is sufficient to activate the taglimit class
      if (querySnapshot.size > 3) {
        this.isTagLimit = true;
      } else {
        this.isTagLimit = false;
      }
      //If you want to update the tags property
      var t = [];
      querySnapshot.forEach(doc => {
        t.push(doc.data());
      });
      this.tags = t;
    });
  }
};
</script>

<style>
.taglimit {
  color: deeppink;
}
</style>
  

Обратите внимание, что вместо замены всего tags массива вы могли бы прослушать «атомарные» изменения в запросе и обновить массив с учетом изменений, см. https://firebase.google.com/docs/firestore/query-data/listen#view_changes_between_snapshots

Комментарии:

1. Это было не совсем то, чего я пытался достичь. Я не могу просто посчитать теги, потому что определенные теги предназначены для определенных игроков, поэтому я сначала получаю все теги, затем с помощью метода countTags я фильтрую до каждой команды и подсчитываю это. Однако, исходя из вашего кода в запросе, я смог решить проблему. Большое вам спасибо!

2. Да, я понял из вашего кода, что существует некоторая фильтрация, основанная на значениях team, если я не ошибаюсь… но, честно говоря, было немного сложно погрузиться в код и быть уверенным, что я применю правильный фильтр в своем ответе …. 🙂 Рад, что я смог вам помочь, однако!