Quasar中如何正确处理Firebase的onAuthStateChanged函数
Quasar 框架下 Firebase 迁移适配方案
现有 Firebase Boot 文件优化
你当前写的firebase.js boot文件基础功能可以正常运行,但没有贴合Quasar boot文件的设计逻辑,稍作调整就能符合最佳实践:
- 初始化Firebase服务时显式传入app实例,避免多环境下出现实例冲突
- 把服务实例挂载到Vue全局属性和Pinia实例上,适配选项式API、Store调用等不同场景
- 利用Quasar异步boot的能力,实现等待鉴权完成再启动应用的逻辑
优化后的src/boot/firebase.js代码:
import { boot } from 'quasar/wrappers' import { markRaw } from 'vue' import { initializeApp } from 'firebase/app' import { getFirestore } from 'firebase/firestore' import { getAuth, onAuthStateChanged } from 'firebase/auth' const firebaseConfig = { apiKey: 'xxxxxxxxxxxxxx', authDomain: 'xxxxxxxxxxxxxx', projectId: 'xxxxxxxxxxxxxx', storageBucket: 'xxxxxxxxxxxxxx', messagingSenderId: 'xxxxxxxxxxxxxx', appId: '1:xxxxxxxxxxxxxx' } // 初始化Firebase核心实例 const firebaseApp = initializeApp(firebaseConfig) // 初始化业务服务 const db = getFirestore(firebaseApp) const auth = getAuth(firebaseApp) export default boot(async ({ app, store, router }) => { // 选项式API场景下可直接通过this.$db、this.$auth访问服务 app.config.globalProperties.$db = db app.config.globalProperties.$auth = auth // 给Pinia全局挂载服务和路由实例,替代原有main.js里给Pinia注入$router的逻辑 if (store) { store.$db = db store.$auth = auth store.$router = markRaw(router) } // 等待首次鉴权状态回调完成再继续应用启动,等价于原来等onAuthStateChanged触发再mount app的逻辑 await new Promise((resolve) => { const unsubscribe = onAuthStateChanged(auth, (user) => { // 首次拿到鉴权结果后同步到用户状态store,替换成你项目里实际的state修改方法即可 if (store) store.commit('user/setCurrentUser', user) unsubscribe() resolve() }) }) }) // 导出实例供组合式API、路由守卫、其他boot文件引入使用 export { db, auth }
原main.js逻辑迁移说明
Quasar内部已经封装了Vue实例创建、Pinia注册、Router注册、根组件挂载的全流程,不需要手动写createApp、mount这类代码,原有main.js里的剩余逻辑按以下方式处理即可:
- 全局样式引入:把原来的
import './input.pcss'路径添加到quasar.config.js配置的css数组中,Quasar会自动全局加载 - 启动时机控制:上面优化后的boot文件已经用异步等待的方式,实现了「等Firebase Auth初始化完成再完成应用加载」的效果,完全避免刷新页面时的登录态闪烁、路由守卫误判问题,不需要手动控制app挂载
运行时登录态监听处理
首次初始化完成后,应用运行过程中的登录态变化(比如用户手动登出、登录态过期),不要放在启动boot里监听,推荐在路由守卫中统一处理:
新建src/boot/router.js文件,写入以下逻辑:
import { boot } from 'quasar/wrappers' import { auth } from './firebase' import { onAuthStateChanged } from 'firebase/auth' export default boot(({ router, store }) => { // 全局路由鉴权守卫 router.beforeEach((to, from, next) => { const needAuth = to.matched.some(record => record.meta.requiresAuth) if (needAuth && !auth.currentUser) return next('/login') next() }) // 全局监听登录态变化 onAuthStateChanged(auth, (user) => { store.commit('user/setCurrentUser', user) // 登录态失效时自动跳转到登录页 const currentRoute = router.currentRoute.value if (!user && currentRoute.meta.requiresAuth) { router.push('/login') } }) })
写完后记得把两个boot文件都注册到quasar.config.js的boot数组里,注意firebase要放在router前面,保证执行顺序正确。
你之前使用的Tailwind CSS、Headless UI不需要做特殊适配,原有组件内的使用方式保持不变,只需要把Tailwind的入口样式文件加入全局css配置即可正常运行。
内容的提问来源于stack exchange,提问作者Pascal Pivaty
相关产品推荐
相关产品推荐

