使用 Vuefire 渲染之前在组件中加载 Firestore 数据
P粉790187507
P粉790187507 2023-08-29 15:05:47
[Vue.js讨论组]

我正在尝试用姓名和个人资料图片填充人员表。该名称源自 Firestore 数据库,图片使用该名称在 Firebase 存储桶中查找相关图片。

我已经观看了几个小时的视频,并且已经浏览了近一百篇文章,因此我的示例代码包含了每个代码的片段,因为我一直在尝试每种组合并得到混合但不成功的结果。

在返回最少错误的当前状态下,我能够成功地使用名称填充表,但是在同一组件中,它无法提取个人资料图片。用于个人资料图片的值已更新,但它从占位符值更新为未定义

GamePlanner.vue

<template>
    <div>
    <Field />
    <Bench />
    <!-- <Suspense>
        <template #default> -->
            <PlanSummary />
        <!-- </template>
        <template #fallback>
            <div class="loading">Loading...</div>
        </template>
    </Suspense> -->
    </div>
</template>

PlanSummary.vue

<template>
    <div class="summaryContainer">
        <div class="inningTableContainer">
            <table class="inningTable">
                <tbody>
                    <!-- <Suspense> -->
                        <!-- <template #default> -->
                            <PlayerRow v-for="player in players.value" :key="player.id" :player="(player as Player)" />
                        <!-- </template> -->

                        <!-- <template #fallback>
                            <tr data-playerid="0">
                                <img class="playerImage" src="https://www.gravatar.com/avatar/205e460b479e2e5b48aec07710c08d50" />
                                Loading players...
                                <span class="playerNumber">00</span>
                            </tr>
                        </template> -->
                    <!-- </Suspense> -->
                </tbody>
            </table>
        </div>

    </div>
</template>

<script setup lang="ts">
import { computed, onErrorCaptured, ref } from "vue";
import { useFirestore, useCollection } from "vuefire";
import { collection } from "firebase/firestore";
import { Player, Inning } from "@/definitions/GamePlanner";
import PlayerRow from "./PlayerRow.vue";

const db = useFirestore();
const gamePlanID = "O278vlB9Xx39vkZvIsdP";

// const players = useCollection(collection(db, `/gameplans/${gamePlanID}/participants`));

// const players = ref(useCollection(collection(db, `/gameplans/${gamePlanID}/participants`)));

// Unhandled error during execution of scheduler flush
// Uncaught (in promise) DOMException: Failed to execute 'insertBefore' on 'Node': The node before which the new node is to be inserted is not a child of this node.
const players = ref(); 
players.value = useCollection(collection(db, `/gameplans/${gamePlanID}/participants`));

// Seeminly infinite loop with "onServerPrefetch is called when there is no active component instance to be associated with."
// Renders 5 (??) undefined players
// One error shown: Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'substring')
// const players = computed(() => useCollection(collection(db, `/gameplans/${gamePlanID}/participants`)));

// onErrorCaptured((error, vm, info) => {
//     console.log("Error loading Summary component: ", error, "vm: ", vm, "info: ", info);
//     throw error;
// });
</script>

PlayerRow.vue

<template>
    <tr :key="player2.id" :data-playerid="player2.id">
        <td>
            <img class="playerImage" :src="playerPictureURL" />
            {{ player2.nickname || player2.firstName + " " + player2.lastName }}
            <span class="playerNumber">{{ player2.playerNumber }}</span>
        </td>
    </tr>
</template>

<script lang="ts" setup>
import { ref, PropType, computed, onMounted, watch } from "vue";
import { useFirebaseStorage, useStorageFileUrl } from "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>, required: true },
    // 'innings': Array<Inning>
});
const player2 = ref(props.player);

// const innings = computed(() => props.innings);

// const playerPictureURL = computed(() => {
//     const playerPictureFilename = `${player2.value.firstName.substring(0,1)}${player2.value.lastName}.png`.toLowerCase();
//     const playerPictureResource = storageRef(fs, `playerPictures/${playerPictureFilename}`);
//     return useStorageFileUrl(playerPictureResource).url.value as string;
// });
// const playerPictureURL = ref(() => {
//     const playerPictureFilename = `${player2.value.firstName.substring(0,1)}${player2.value.lastName}.png`.toLowerCase();
//     const playerPictureResource = storageRef(fs, `playerPictures/${playerPictureFilename}`);
//     return useStorageFileUrl(playerPictureResource).url.value as string;
// });

const playerPictureURL = ref("https://www.gravatar.com/avatar/205e460b479e2e5b48aec07710c08d50");
async function getPlayerPictureURL() {
    console.log("PlayerRow.ts getPlayerPictureURL");
    const playerPictureFilename = `${player2.value.firstName.substring(0,1)}${player2.value.lastName}.png`.toLowerCase();
    const playerPictureResource = await storageRef(fs, `playerPictures/${playerPictureFilename}`);
    playerPictureURL.value = await useStorageFileUrl(playerPictureResource).url.value as 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>

我的印象是 需要包装 组件,因为我正在使用 storageRef 和 < code>useStorageUrl 方法,但它似乎引入了更多问题。根据 vuefire 文档并检查代码本身的定义,它们似乎并不是异步的,但是尝试立即调用它们不会产生立即/实际结果。

相关软件包版本

{
    "vue": "^3.2.45"
    "firebase": "^9.15.0",
    "typescript": "^4.9.3",
    "vite": "^4.0.0",
    "vue-router": "^4.1.6",
    "vue-tsc": "^1.0.11",
    "vuefire": "3.0.0-beta.6"
}

P粉790187507
P粉790187507

全部回复(1)
P粉432906880

根据这个文档我们应该使用useCollection 包含 collection 作为参数,如下所示:

const todos = useCollection(collection(db, `/gameplans/${gamePlanID}/participants`))

我发现您正在以正确的方式使用它,但您可以将其直接分配给 players 变量,而不是分配给 ref 。当您尝试使用此反应式对象作为 ref 对象的值时,这是不受支持的。

您可以通过更改此行来解决您的问题:

const players = ref(); 
players.value = useCollection(collection(db, `/gameplans/${gamePlanID}/participants`));

致:

const players = useCollection(collection(db, `/gameplans/${gamePlanID}/participants`));

有关此主题的更多信息,您可以浏览以下文档

热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号