【问题标题】:How to prevent any routing before some async data (in Vuex store) has loaded?如何在某些异步数据(在 Vuex 存储中)加载之前防止任何路由?
【发布时间】:2018-12-31 21:20:59
【问题描述】:

在我的应用程序中,我需要在路由开始之前将一些数据加载到 VueX 存储中(例如用户会话)。

竞态条件的示例如下:

// In routes definition
{
  name: 'login',
  path: '/login',
  component: Login,
  meta: {
    goToIndexIf: () => store.getters['auth/loggedIn']
  }
}

在这种情况下,可能会在从服务器接收到用户之前执行路由保护。

使用条件渲染无济于事,因为在渲染模板中使用或不使用<router-view v-if="storeReady"> 都会执行路由保护。

如何让我的所有路由等待一些异步数据?

【问题讨论】:

    标签: javascript vue.js vue-router vuex race-condition


    【解决方案1】:

    解决方案很简单。将 init 或等效的 Vuex action 添加到商店的相关部分。
    它应该返回您的应用程序绝对需要*的所有数据请求的Promise

    init ({ dispatch }) {       // Could also be async and use await instead of return
      return Promise.all([
        dispatch('getUserSession'), // Using another action
        dispatch('auth/init'),      // In another module
        fetch('tehKittenz')         // With the native fetch API
        // ...
      ])
    }
    

    上面的代码可以使用任何返回Promise的东西。

    然后使用beforeEach在您的路由器中创建一个global navigation guard
    该守卫将等待由 dispatch 生成的对 store 的承诺。

    // In your router initialization code
    const storeInit = store.dispatch('init')
    
    // Before all other beforeEach
    router.beforeEach((to, from, next) => {
      storeInit.then(next)
        .catch(e => {
          // Handle error
        })
    })
    

    这样,如果在存储完全加载之前发生路由,路由器将简单地等待。
    如果路由发生在之后,promise 已经处于fulfilled 状态并且路由将继续进行。

    不要忘记使用conditional rendering 之类的东西,以免在路由等待数据时显示空白屏幕。


    *:只要正在获取数据,这将阻止所有路由和导航。当心。

    【讨论】:

      【解决方案2】:

      我所做的和工作正常的是将我的 Vue 实例 (new Vue({... })) 包装在 .then() "Promise" 中。如果一切正常并解决,这个承诺将解决(null)发生错误时出现错误,因此我可以根据错误有条件地渲染 vue 实例

      here i call my async function and wait until it loads the store and then initialize my app

      my async function that uses the token to get me the data

      这样做将使处理获取的存储数据的路由守卫正常工作

      希望对我有所帮助,如果我的英语不好,请见谅:)

      【讨论】:

        【解决方案3】:

        自从第一次提出这个问题以来,vue-router (v3.5.1) 已经向check for the initial navigation 公开了执行此类操作并仅在第一条路由上运行的能力。

        比较 fromVueRouter.START_LOCATION

        import VueRouter from 'vue-router'
        
        const router = new VueRouter({
          // ...
        })
        
        router.beforeEach((to, from, next) => {
          if (from === VueRouter.START_LOCATION) {
            // initial navigation, handle Vuex initialization/hydration.
            initalizeOrWait().then((isLoggedIn) => {
              // handle navigation or pass to guard how it fits your needs here etc.
              next();
            });
          } else {
            next();
          }
        })
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-06-15
          • 2020-07-24
          • 2021-04-19
          • 2021-08-13
          相关资源
          最近更新 更多