首页 文章

如何在vue-router中访问异步存储数据以便在beforeEnter hook中使用?

提问于
浏览
9

如何在beforeEnter中访问通过商店操作异步检索的商店数据?

import store from './vuex/store';

store.dispatch('initApp'); // in here, async data will be fetched and assigned to the store's state

// following is an excerpt of the routes object:
{
  path: '/example',
  component: Example,
  beforeEnter: (to, from, next) =>
  {
    if (store.state.asyncData) {
      // the above state is not available here, since it
      // it is resolved asynchronously in the store action
    }
  }
}

这对于第一页加载或页面重新加载,获取初始化数据以及路由器需要等待该数据以允许用户访问该页面时尤为重要 .

路由器是否可以“等待”获取数据?或者,与异步vuex商店数据相结合处理导航防护的最佳方法是什么?

(哦和预先填充“asyncData”不能解决,因为beforeEnter挂钩需要从数据库做出真实数据的决定,而不是默认数据)

3 回答

  • 8

    您可以通过从vuex操作返回一个promise来完成它,因为它被解释为here并从 beforeEnter 本身调用dispatch .

    代码应如下所示:

    import store from './vuex/store';
    
    
    // following is an excerpt of the routes object:
    {
      path: '/example',
      component: Example,
      beforeEnter: (to, from, next) =>
      {
        store.dispatch('initApp').then(response => {
            // the above state is not available here, since it
            // it is resolved asynchronously in the store action
        }, error => {
            // handle error here
        })         
      }
    }
    
  • 4

    在每次路由更改之前,您是否真的需要从服务器异步获取数据,或者您是否只需要保留商店中的某些数据,以便在重新加载页面或用户使用直接链接时它们不会“消失”?

    如果是后者,你可以 persist the auth data (e.g. JWT token) in localStorage/cookie 然后在初始化期间简单地从存储中提取它们(并将它们提交到存储) - 这应该是一个同步动作 .

    您也可以使用vuex-persistedstate来存储 persist the whole state ,这样它就不需要保湿了 .

    如果在首次加载或页面重新加载之前需要 fetch some data asynchronously once ,则可以调度存储操作并在 then() 回调中初始化Vue实例 - 但这可能取决于您的实现 . 像这样的东西(在 main.js ):

    import Vue from 'vue';
    import VueRouter from 'vue-router';
    import { sync } from 'vuex-router-sync';
    
    // contains VueRouter instance and route definitions
    import router from 'src/router/router';
    // contains Vuex.Store instance. I guess this is './vuex/store' in your example?
    import store from 'src/store/store';
    
    // sync the router with vuex store using vuex-router-sync
    Vue.use(VueRouter);
    sync(store, router);
    
    // dispatch init action, doing asynchronous stuff, commiting to store
    store.dispatch('initApp').then(() => {
        // create the main Vue instance and mount it
        new Vue({
            router,
            store           
        }).$mount('#app');
    });
    
  • 4

    我已经通过使用store.watch()没有初始值解决了这个问题,并在初始化时返回最新值 .

    这是我的示例代码

    async function redirectIfNotAuth (to, from, next) {
      const user = await getUserState()
      if (user === null) {
        next({ name: 'auth' })
      } else {
        next()
      }
    }
    
    function getUserState () {
      return new Promise((resolve, reject) => {
        if (store.state.user === undefined) {
          const unwatch = store.watch(
            () => store.state.user,
            (value) => {
              unwatch()
              resolve(value)
            }
          )
        } else {
          resolve(store.state.user)
        }
      })
    }
    
    
    /* STORE */
    const store = new Vuex.Store({
      state: {
        user: undefined
      }
    })
    
    /* ROUTER */
    new Router({
      routes: [
        {
          path: '',
          name: 'home',
          component: Home,
          beforeEnter: redirectIfNotAuth
        },
        {
          path: '/signin',
          name: 'auth',
          component: Auth,
        }
      ]
    })
    

相关问题