因此,我公开找到的所有问题答案都没有太大帮助,尽管它们“起作用”,但它们确实令人难以置信。
基本上我有一个vuex变量appLoading
,最初它是true,但是一旦完成所有异步操作,它就会设置为false。我还有另一个名为user
的vuex变量,它包含用户信息,这些信息一旦返回就将从异步操作中分派。
然后我还有一个路由器守卫来检查;
router.beforeEach((to, from, next) => {
if (to.matched.some(route => route.meta.requiresAuth)) {
if (store.getters.getUser) {
return next();
}
return router.push({ name: 'index.signup' });
}
return next();
});
然后在我最初的Vue实例中显示加载状态,直到appLoading = false;
现在这个“有效”,但是确实有一个困扰我的问题。如果您加载该页面,则会看到应该看到的相反页面的“闪烁”。
因此,如果您已登录,则在首次加载时会看到注册页面的闪烁。如果您尚未登录,则将看到已登录页面的闪烁。
这很烦人,我将问题缩小到我的身份验证卫士。
似乎由于user
不存在而将注册页面推送到路由器,然后由于user
被提交而立即推送到登录页面。
我该如何以一种不令人讨厌的方式解决此问题,因为这有点烦人,令人沮丧的是,Vue甚至没有一点点官方文档/示例来解决如此普遍的问题,尤其是因为如此众多的Web应用程序都使用身份验证。
希望有人可以提供帮助。 :)
答案 0 :(得分:1)
根据评论中的讨论:
最适合您的情况是将appLoading
变量设为promise
。这样一来,您就可以执行操作或等待操作,直到解决您的应用程序数据为止。
考虑appLoading
用API调用promise初始化的promise,路由器钩子将类似于:
router.beforeEach((to, from, next) => {
appLoading.then(() => {
if (to.matched.some(route => route.meta.requiresAuth)) {
if (store.getters.getUser) {
return next();
}
return router.push({ name: "index.signup" });
}
return next();
});
});
您可能只想将其保留为init
代码的导出内容,而不是将其保留在Vuex中。 Vuex用于在组件之间共享的反应性数据。
答案 1 :(得分:0)
路由器 beforeEach hook 可以是一个 promise 并等待 Vuex 操作完成。类似的东西:
router.beforeEach(async (to, from, next) => {
if (to.matched.some(route => route.meta.requiresAuth)) {
await store.dispatch('init');
if (store.getters.getUser) {
return next();
}
return router.push({ name: 'index.signup' });
}
return next();
});
'init' 操作应该返回一个承诺:
const actions = {
async init({commit}) {
const user = await service.getUser();
commit('setUser', user);
}
}
这种方法存在的问题是,每当我们导航到给定页面时,它都会触发“init”操作,该操作将从服务器获取用户。我们只想在没有用户的情况下获取用户,因此我们可以更新商店检查它是否有用户并相应地获取它:
const state = {
user: null
}
const actions = {
async init({commit, state}) {
if(!state.user) {
const user = await service.getUser();
commit('setUser', user);
}
}
}