使用 Vue.js3,我已在一个组件中成功登录 Google Firebase 身份验证,然后使用以下方法将 Firebase 用户变量存储在 Vuex 存储中:
store.commit('setUser', userData);
之后,我可以在另一个组件中访问它:
const currentUser = computed(() => store.getters.currentUser);
但是,我无法使用上述方法在 router.js 文件中检索此用户变量。 我当前的解决方法是为商店创建一个操作,一个像这样的异步 fetchUser 函数。它不断尝试检索 Firebase 用户变量、提交并返回。如果没有 Promise 计时器 setTimeout,即使我使用异步等待,它也会立即返回 Null 值。
// store/index.js
import { createStore } from 'vuex';
const store = createStore({
state: {
user: null,
},
mutations: {
setUser(state, user) {
state.user = user;
},
},
actions: {
async fetchUser({ commit }) {
try {
let fetchedUser = this.getters.currentUser;
let elapsedTime = 0;
const maxWaitTime = 10000; // 10 seconds
while (!fetchedUser && elapsedTime < maxWaitTime) {
fetchedUser = this.getters.currentUser;
elapsedTime += 200;
await new Promise(resolve => setTimeout(resolve, 50));
}
if (!fetchedUser) {
throw new Error('Timeout: Unable to fetch user within 10 seconds.');
}
commit('setUser', fetchedUser);
return fetchedUser;
} catch (error) {
console.error('Error fetching user:', error);
throw error;
}
},
},
getters: {
currentUser: state => state.user,
},
});
export default store;
我的 router.js 文件:
const routes = [
{
path: '/',
name: 'HomePage',
component: HomePage,
beforeEnter: async (to, from, next) => {
const store = useStore();
try {
await store.dispatch('fetchUser');
const currentUser = await store.state.user;
if (!currentUser) {
// redirect to GoogleLogin page
next({ name: 'GoogleLogin' });
} else {
// Stay at homepage
next();
}
} catch (error) {
console.error('Error fetching user:', error);
next();
}
}
},
{
path: '/login',
name: 'GoogleLogin',
component: GoogleLogin
},
];
虽然此解决方法有效,但性能很差,通常需要 800 毫秒才能获取。 是的,或者,我可以向 Router.js 添加另一个 onAuthStateChanged 或在 Main.js 的 onAuthStateChanged 上推送 router.push 来检查并重定向登录页面。
firebaseAuth.onAuthStateChanged((userData) => {
store.commit('setUser', userData);
console.log('Login check: ', userData);
if (!userData) {
router.push('/login'); // in main.js file
//next({ name: 'GoogleLogin' }); // if use in router.js
} else {
//...
}
});
但有时,我仍然需要在 Router.js 中使用 Vuex 变量,那么我该如何改进这一点,或者是否有更好的方法在 Router 文件中使用 Vuex 全局变量?
对我来说,使用 Vuex store 到 router.js 中是最好的方法,因为这是直接导入并使用它来访问状态的最直接的方法。
import store from './store'; // Import your Vuex store
router.beforeEach((to, from, next) => {
const currentUser = store.getters.currentUser;
if (!currentUser) {
next({ name: 'GoogleLogin' });
} else {
next();
}
});