#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, если я не ошибаюсь… но, честно говоря, было немного сложно погрузиться в код и быть уверенным, что я применю правильный фильтр в своем ответе …. 🙂 Рад, что я смог вам помочь, однако!