Vue.js 如何让Vue路由器防护等待Vuex?

Vue.js 如何让Vue路由器防护等待Vuex?,vue.js,vuex,vue-router,Vue.js,Vuex,Vue Router,所以,我在公开场合找到的关于这个问题的所有答案都不是很有帮助,尽管这些答案“有效”,但它们都非常粗糙 基本上,我有一个vuex变量,appLoading,它最初为true,但在所有异步操作完成后设置为false。我还有另一个名为user的vuex变量,它包含异步操作返回后发送的用户信息 然后,我还有一个路由器守卫,负责检查 router.beforeEach((to, from, next) => { if (to.matched.some(route => route.meta

所以,我在公开场合找到的关于这个问题的所有答案都不是很有帮助,尽管这些答案“有效”,但它们都非常粗糙

基本上,我有一个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

现在这个“工作”,但有一个问题,这是真正困扰我。如果你加载页面,你会看到你应该看到的另一个页面的“闪烁”

所以,如果您登录,在第一次加载时,您将看到注册页面的闪烁。如果您没有登录,您将看到登录页面闪烁

这是相当恼人的,我把问题缩小到我的授权保护。 由于
用户
不存在,它似乎正在将注册页面推送到路由器,然后由于
用户
被提交,它立即推送到登录页面

我如何才能以一种不被黑客攻击的方式解决这个问题,因为Vue对于这样一个常见的问题甚至连一点官方文档/示例都没有,这有点烦人,有点令人沮丧,尤其是因为如此大量的Web应用程序使用身份验证


希望有人能提供一些帮助。:)

根据评论中的讨论:

对于您的案例,最好的方法是将您的
appLoading
变量设置为
promise
。这就是你可以做事情或等待事情的方式,直到你的应用程序数据被解析

考虑到
appLoading
一个您用api调用承诺初始化的承诺,您的路由器挂钩将如下所示:

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用于通过组件共享的反应式数据。

每个钩子之前的路由器可以是一个承诺,并等待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);
    }
  }
}

你的
appLoading
实际上应该是一个
promise
,你可以
在你的hooks@pranavjindal999默认情况下是这样的吗?是真实的状态本身是一个承诺,还是一个获得者?假设它是getter,我能用一个if语句包装我的路由器保护吗`如果(store.getters.appLoading){guard…}?如果希望直接使用getter或state访问它,则由您决定。但你描述的方式行不通。Hooks不知道你的状态何时改变。你必须让它成为承诺,
然后
把整个钩子都钩住承诺。@pranavjindal999我不确定我是否遵守。我想我知道大概的意思,但你能举个小例子吗?谢谢:)嘿,像这样的东西行吗<代码>导出常量init=newpromise((解析,拒绝)=>{if(store.getters.appisload==false){resolve();}else{reject();})我希望你能提供更多关于承诺包装部分的信息。我尝试了许多不同的方法,但都没有成功/你似乎缺乏对承诺的理解。我建议你重新审视承诺。好资源:问题在于
路由器。beforeach
钩子在存储操作之前执行。问题的答案是根据存储中
appLoading
状态的值,从这个钩子内部调用操作。如果未定义,则调用操作;如果为true,则查看存储;如果为false,则表示您想要的状态已提交。您需要使用async/await或
Promise.then()