Vue3 关联Firestore调用的条件provide用户登录后未更新问题求解
问题根因
- Vue的
provide传递的是引用快照,之前的写法直接将notifications变量重新赋值为新的响应式实例,已经provide给后代的旧空ref引用不会同步更新,导致后代拿不到最新数据 - 兄弟组件无法互相provide是因为Vue的依赖注入是祖先-后代链路传递,同级组件没有公共祖先的话无法通过该方式通信,在根组件/布局父组件统一provide即可覆盖所有子级、兄弟级组件的注入需求
解决方案
实现逻辑
- 全程使用同一个响应式ref实例存储通知数据,仅修改实例的
value属性,不替换实例本身 - 新增请求锁标记,保证仅发起1次Firestore拉取请求
- 监听用户登录状态,登录成功且未拉取过数据时写入拉取结果
- 在公共祖先组件(比如根组件、外层布局组件)将固定的ref实例provide给所有后代
代码示例
import { ref, watch, provide } from 'vue' // 初始化固定响应式容器,全程不替换该实例 const notifications = ref([]) // 请求锁,避免重复触发Firestore请求 let hasFetchedNotifications = false // 监听用户状态变化,immediate保证初始化已登录场景直接拉取 watch(user, (currentUser) => { // 未登录或已拉取过数据直接跳过 if (!currentUser?.displayName || hasFetchedNotifications) { // 登出时可选清空数据并重置锁 if (!currentUser) { notifications.value = [] hasFetchedNotifications = false } return } // 拉取通知数据 const { documents } = getCollection('profiles', null, currentUser.displayName, 'notifications') // 写入已有ref的value,不要替换notifications变量本身 notifications.value = documents.value // 标记已拉取,锁死重复请求 hasFetchedNotifications = true }, { immediate: true }) // provide传递固定的ref实例 provide('notifications', notifications)
后代组件使用
所有子孙、兄弟组件直接inject即可,数据会自动响应更新:
import { inject } from 'vue' const notifications = inject('notifications') // 模板直接使用 {{ notifications }} 即可,登录完成后自动同步数据
内容的提问来源于stack exchange,提问作者Taylor Chance
相关产品推荐
相关产品推荐

