Laden Sie Firestore-Daten in Komponenten, bevor Sie sie mit Vuefire rendern
<p>Ich versuche, eine Personentabelle mit Namen und Profilbildern zu füllen. Der Name wird aus der Firestore-Datenbank abgeleitet und vom Bild verwendet, um verwandte Bilder im Firebase-Bucket zu finden. </p>
<p>Ich habe stundenlang Videos angeschaut und fast hundert Artikel durchgesehen, daher enthält mein Beispielcode Ausschnitte von jedem Code, da ich jede Kombination ausprobiert und eine Mischung erhalten habe, aber keine erfolgreichen Ergebnisse erzielt habe. </p>
<p>Im aktuellen Zustand, der nur minimale Fehler zurückgibt, kann ich die Tabelle erfolgreich mit den Namen füllen, allerdings schlägt das Extrahieren des Profilbilds innerhalb derselben Komponente fehl. Der für das Profilbild verwendete Wert wurde aktualisiert, jedoch von einem Platzhalterwert auf <code>undefiniert</code>. </p>
<p><strong>GamePlanner.vue</strong></p>
<pre class="brush:vue;toolbar:false;"><template>
<div>
<Feld />
<Bank />
<!-- <Spannung>
<template #default>
<PlanSummary />
<!-- </template>
<template #fallback>
<div class="loading">Loading...</div>
</template>
</Suspense>
</div>
</template>
</pre>
<p><strong>PlanSummary.vue</strong></p>
<pre class="brush:vue;toolbar:false;"><template>
<div class="summaryContainer">
<div class="inningTableContainer">
<table class="inningTable">
<tbody>
<!-- <Spannung> -->
<!-- <template #default> -->
<PlayerRow v-for="Spieler in spieler.value" :key="player.id" :player="(Spieler als Spieler)" />
<!-- </template> -->
<!-- <template #fallback>
<tr data-playerid="0">
<img class="playerImage" src="https://www.gravatar.com/avatar/205e460b479e2e5b48aec07710c08d50" />
Spieler werden geladen...
<span class="playerNumber">00</span>
</tr>
</template> -->
<!-- </Suspense> -->
</tbody>
</table>
</div>
</div>
</template>
<script setup lang="ts">
import { berechnet, onErrorCaptured, ref } aus „vue“;
import { useFirestore, useCollection } aus „vuefire“;
{ Sammlung } aus „Firebase/Firestore“ importieren;
import { Player, Inning } from "@/definitions/GamePlanner";
importiere PlayerRow aus „./PlayerRow.vue“;
const db = useFirestore();
const gamePlanID = "O278vlB9Xx39vkZvIsdP";
// const player = useCollection(collection(db, `/gameplans/${gamePlanID}/participants`));
// const player = ref(useCollection(collection(db, `/gameplans/${gamePlanID}/participants`)));
// Unbehandelter Fehler während der Ausführung des Scheduler-Flushes
// Nicht abgefangen (im Versprechen) DOMException: 'insertBefore' konnte nicht auf 'Node' ausgeführt werden: Der Knoten, vor dem der neue Knoten eingefügt werden soll, ist kein untergeordnetes Element dieses Knotens.
const player = ref();
player.value = useCollection(collection(db, `/gameplans/${gamePlanID}/participants`));
// Scheinbar Endlosschleife mit „onServerPrefetch wird aufgerufen, wenn keine aktive Komponenteninstanz vorhanden ist, der zugeordnet werden kann.“
// Rendert 5 (??) undefinierte Spieler
// Ein Fehler wird angezeigt: Uncaught (im Versprechen) TypeError: Eigenschaften von undefiniert können nicht gelesen werden (liest „Teilzeichenfolge“)
// constplayers = berechnet(() => useCollection(collection(db, `/gameplans/${gamePlanID}/participants`)));
// onErrorCaptured((error, vm, info) => {
// console.log("Fehler beim Laden der Zusammenfassungskomponente: ", Fehler, "vm: ", vm, "info: ", info);
// Fehler werfen;
// });
</script>
</pre>
<p><strong>PlayerRow.vue</strong></p>
<pre class="brush:vue;toolbar:false;"><template>
<tr :key="player2.id" :data-playerid="player2.id">
<td>
<img class="playerImage" :src="playerPictureURL" />
{{ player2.nickname || Spieler2.Vorname + " " + Spieler2.Nachname }}
<span class="playerNumber">{{ player2.playerNumber }}</span>
</td>
</tr>
</template>
<script lang="ts" Setup>
import { ref, PropType, berechnet, onMounted, watch } aus „vue“;
import { useFirebaseStorage, useStorageFileUrl } aus „vuefire“;
import { ref as storageRef } from 'firebase/storage';
import { Player, Inning } from "@/definitions/GamePlanner";
const fs = useFirebaseStorage();
const props = defineProps({
'player': { type: Object as PropType<Player>, erforderlich: true },
// 'Innings': Array<Inning>
});
const player2 = ref(props.player);
// const innings = berechnet(() => props.innings);
// const playerPictureURL = berechnet(() => {
// const playerPictureFilename = `${player2.value.firstName.substring(0,1)}${player2.value.lastName}.png`.toLowerCase();
// const playerPictureResource = storageRef(fs, `playerPictures/${playerPictureFilename}`);
// useStorageFileUrl(playerPictureResource).url.value als String zurückgeben;
// });
// const playerPictureURL = ref(() => {
// const playerPictureFilename = `${player2.value.firstName.substring(0,1)}${player2.value.lastName}.png`.toLowerCase();
// const playerPictureResource = storageRef(fs, `playerPictures/${playerPictureFilename}`);
// useStorageFileUrl(playerPictureResource).url.value als String zurückgeben;
// });
const playerPictureURL = ref("https://www.gravatar.com/avatar/205e460b479e2e5b48aec07710c08d50");
asynchrone Funktion getPlayerPictureURL() {
console.log("PlayerRow.ts getPlayerPictureURL");
const playerPictureFilename = `${player2.value.firstName.substring(0,1)}${player2.value.lastName}.png`.toLowerCase();
const playerPictureResource = waiting storageRef(fs, `playerPictures/${playerPictureFilename}`);
playerPictureURL.value = warte auf useStorageFileUrl(playerPictureResource).url.value als String;
}
onMounted(() => {
console.log("PlayerRow.ts onMounted");
getPlayerPictureURL();
});
watch(playerPictureURL, (newVal, oldVal) => {
console.log("PlayerRow.ts watch playerPictureURL");
console.log("newVal: " + newVal);
console.log("oldVal: " + oldVal);
});
</script>
</pre>
<p>我的印象是 <code><Suspense></code> 需要包装 <code><PlayerRow></code> 组件,因为我正在使用 <code>storageRef</code> 和 < code>useStorageUrl</code> 方法,但它似乎引入了更多问题.根据 vuefire但是尝试立即调用它们不会产生立即/实际结果.</p>
<p><strong>相关软件包版本</strong></p>
<pre class="brush:json;toolbar:false;">{
"vue": "^3.2.45"
"firebase": "^9.15.0",
"Typoskript": "^4.9.3",
"vite": "^4.0.0",
„vue-router“: „^4.1.6“,
"vue-tsc": "^1.0.11",
„vuefire“: „3.0.0-beta.6“
}
</pre></p>