如何在Vue 3 + VueFire中动态更新网站标题与Favicon?
解决Vue3+Pinia+VueFire异步数据加载后修改标题和Favicon的问题
核心问题确实是你判断的:赋值操作执行时,Firestore的数据还未加载完成,placeStore.placeInfo此时为undefined,导致标题和Favicon赋值失败。以下是两种可靠的解决方法:
方法一:在组件中用watch监听数据变化
利用Vue的响应式特性,监听placeInfo的状态变化,当数据加载完成后再执行赋值逻辑:
<template> <div class="place" v-if="placeStore.placeInfo"> <h1>{{ placeStore.placeInfo.placeName }}</h1> </div> </template> <script setup> import { usePlaceStore } from '@/stores/PlaceStore'; import { watch } from 'vue'; const placeStore = usePlaceStore(); const favicon = document.querySelector("link[rel~='icon']"); // 监听placeInfo变化,数据就绪后修改标题和Favicon watch( () => placeStore.placeInfo, (newPlaceInfo) => { if (newPlaceInfo) { document.title = newPlaceInfo.placeTitle; if (favicon && newPlaceInfo.placeFaviconUrl) { favicon.href = newPlaceInfo.placeFaviconUrl; } } }, { immediate: true } // 立即执行一次,避免数据已加载时错过触发 ); </script>
方法二:在Pinia Store中封装逻辑(可选)
如果希望把标题和Favicon的修改逻辑封装到Store里,可以在Store内部添加监听:
import { defineStore } from 'pinia'; import { useFirestore, useDocument } from 'vuefire'; import { doc } from 'firebase/firestore'; import { useRoute } from 'vue-router'; import { watch } from 'vue'; export const usePlaceStore = defineStore('PlaceStore', () => { const route = useRoute(); const placeName = route.params.placeName; const db = useFirestore(); const placeInfo = useDocument(() => doc(db, 'places', placeName), { once: true }); // Store内部监听数据加载完成,修改标题和Favicon watch( () => placeInfo.value, (newPlaceInfo) => { if (newPlaceInfo) { document.title = newPlaceInfo.placeTitle; const favicon = document.querySelector("link[rel~='icon']"); if (favicon && newPlaceInfo.placeFaviconUrl) { favicon.href = newPlaceInfo.placeFaviconUrl; } } }, { immediate: true } ); return { placeInfo }; });
额外注意事项
- 确认Firestore返回的文档中确实存在
placeTitle和placeFaviconUrl字段,避免拼写错误 - 给Favicon赋值添加判断,防止元素不存在或字段为空时抛出错误
- 由于你使用了
{ once: true }配置,数据只会加载一次,监听逻辑也只会触发一次,完全匹配你的需求
内容的提问来源于stack exchange,提问作者Obed Monsalve
相关产品推荐
相关产品推荐

