使用 Vuefire 渲染之前在组件中加载 Firestore 数据
P粉790187507
P粉790187507 2023-08-29 15:05:47
[Vue.js讨论组]
<p>我正在尝试用姓名和个人资料图片填充人员表。该名称源自 Firestore 数据库,图片使用该名称在 Firebase 存储桶中查找相关图片。</p> <p>我已经观看了几个小时的视频,并且已经浏览了近一百篇文章,因此我的示例代码包含了每个代码的片段,因为我一直在尝试每种组合并得到混合但不成功的结果。</p> <p>在返回最少错误的当前状态下,我能够成功地使用名称填充表,但是在同一组件中,它无法提取个人资料图片。用于个人资料图片的值已更新,但它从占位符值更新为<code>未定义</code>。</p> <p><strong>GamePlanner.vue</strong></p> <pre class="brush:vue;toolbar:false;">&lt;template&gt; &lt;div&gt; &lt;Field /&gt; &lt;Bench /&gt; &lt;!-- &lt;Suspense&gt; &lt;template #default&gt; --&gt; &lt;PlanSummary /&gt; &lt;!-- &lt;/template&gt; &lt;template #fallback&gt; &lt;div class=&quot;loading&quot;&gt;Loading...&lt;/div&gt; &lt;/template&gt; &lt;/Suspense&gt; --&gt; &lt;/div&gt; &lt;/template&gt; </pre> <p><strong>PlanSummary.vue</strong></p> <pre class="brush:vue;toolbar:false;">&lt;template&gt; &lt;div class=&quot;summaryContainer&quot;&gt; &lt;div class=&quot;inningTableContainer&quot;&gt; &lt;table class=&quot;inningTable&quot;&gt; &lt;tbody&gt; &lt;!-- &lt;Suspense&gt; --&gt; &lt;!-- &lt;template #default&gt; --&gt; &lt;PlayerRow v-for=&quot;player in players.value&quot; :key=&quot;player.id&quot; :player=&quot;(player as Player)&quot; /&gt; &lt;!-- &lt;/template&gt; --&gt; &lt;!-- &lt;template #fallback&gt; &lt;tr data-playerid=&quot;0&quot;&gt; &lt;img class=&quot;playerImage&quot; src=&quot;https://www.gravatar.com/avatar/205e460b479e2e5b48aec07710c08d50&quot; /&gt; Loading players... &lt;span class=&quot;playerNumber&quot;&gt;00&lt;/span&gt; &lt;/tr&gt; &lt;/template&gt; --&gt; &lt;!-- &lt;/Suspense&gt; --&gt; &lt;/tbody&gt; &lt;/table&gt; &lt;/div&gt; &lt;/div&gt; &lt;/template&gt; &lt;script setup lang=&quot;ts&quot;&gt; import { computed, onErrorCaptured, ref } from &quot;vue&quot;; import { useFirestore, useCollection } from &quot;vuefire&quot;; import { collection } from &quot;firebase/firestore&quot;; import { Player, Inning } from &quot;@/definitions/GamePlanner&quot;; import PlayerRow from &quot;./PlayerRow.vue&quot;; const db = useFirestore(); const gamePlanID = &quot;O278vlB9Xx39vkZvIsdP&quot;; // 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 &quot;onServerPrefetch is called when there is no active component instance to be associated with.&quot; // Renders 5 (??) undefined players // One error shown: Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'substring') // const players = computed(() =&gt; useCollection(collection(db, `/gameplans/${gamePlanID}/participants`))); // onErrorCaptured((error, vm, info) =&gt; { // console.log(&quot;Error loading Summary component: &quot;, error, &quot;vm: &quot;, vm, &quot;info: &quot;, info); // throw error; // }); &lt;/script&gt; </pre> <p><strong>PlayerRow.vue</strong></p> <pre class="brush:vue;toolbar:false;">&lt;template&gt; &lt;tr :key=&quot;player2.id&quot; :data-playerid=&quot;player2.id&quot;&gt; &lt;td&gt; &lt;img class=&quot;playerImage&quot; :src=&quot;playerPictureURL&quot; /&gt; {{ player2.nickname || player2.firstName + &quot; &quot; + player2.lastName }} &lt;span class=&quot;playerNumber&quot;&gt;{{ player2.playerNumber }}&lt;/span&gt; &lt;/td&gt; &lt;/tr&gt; &lt;/template&gt; &lt;script lang=&quot;ts&quot; setup&gt; import { ref, PropType, computed, onMounted, watch } from &quot;vue&quot;; import { useFirebaseStorage, useStorageFileUrl } from &quot;vuefire&quot;; import { ref as storageRef } from 'firebase/storage'; import { Player, Inning } from &quot;@/definitions/GamePlanner&quot;; const fs = useFirebaseStorage(); const props = defineProps({ 'player': { type: Object as PropType&lt;Player&gt;, required: true }, // 'innings': Array&lt;Inning&gt; }); const player2 = ref(props.player); // const innings = computed(() =&gt; props.innings); // const playerPictureURL = computed(() =&gt; { // 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(() =&gt; { // 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(&quot;https://www.gravatar.com/avatar/205e460b479e2e5b48aec07710c08d50&quot;); async function getPlayerPictureURL() { console.log(&quot;PlayerRow.ts getPlayerPictureURL&quot;); 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(() =&gt; { console.log(&quot;PlayerRow.ts onMounted&quot;); getPlayerPictureURL(); }); watch(playerPictureURL, (newVal, oldVal) =&gt; { console.log(&quot;PlayerRow.ts watch playerPictureURL&quot;); console.log(&quot;newVal: &quot; + newVal); console.log(&quot;oldVal: &quot; + oldVal); }); &lt;/script&gt; </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;">{ &quot;vue&quot;: &quot;^3.2.45&quot; &quot;firebase&quot;: &quot;^9.15.0&quot;, &quot;typescript&quot;: &quot;^4.9.3&quot;, &quot;vite&quot;: &quot;^4.0.0&quot;, &quot;vue-router&quot;: &quot;^4.1.6&quot;, &quot;vue-tsc&quot;: &quot;^1.0.11&quot;, &quot;vuefire&quot;: &quot;3.0.0-beta.6&quot; } </pre></p>
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`));

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

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

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