如何在加载某些异步数据(在 Vuex 存储中)之前防止任何路由?
How to prevent any routing before some async data (in Vuex store) has loaded?
在我的应用程序中,我需要在路由开始之前将一些数据加载到 VueX 存储中(例如用户会话)。
竞争条件的示例如下:
// In routes definition
{
name: 'login',
path: '/login',
component: Login,
meta: {
goToIndexIf: () => store.getters['auth/loggedIn']
}
}
在这种情况下,路由守卫可能会在从服务器接收到用户之前执行。
使用条件渲染没有帮助,因为路由守卫在渲染模板中使用或不使用 <router-view v-if="storeReady">
执行。
如何让我的所有路由都等待一些异步数据?
解决方法很简单。在商店的相关部分添加 init
或等效的 Vuex action
。
它应该 return 您的应用程序 绝对需要的所有数据请求的 Promise
*:
init ({ dispatch }) { // Could also be async and use await instead of return
return Promise.all([
dispatch('getUserSession'), // Using another <b>action</b>
dispatch('auth/init'), // In another module
fetch('tehKittenz') // With the native <b>fetch</b> API
// ...
])
}
以上代码可以使用任何 return 是 Promise
。
然后只需使用 beforeEach
在您的路由器中创建一个 global navigation guard。
这个守卫将等待 dispatch
对商店产生的承诺。
// In your router initialization code
const storeInit = store.dispatch('init')
// Before <b>all other beforeEach</b>
router.beforeEach((to, from, next) => {
storeInit.then(next)
.catch(e => {
// Handle error
})
})
这样,如果路由发生在商店完全加载之前,路由器将简单地等待。
如果之后发生路由,promise 将已经处于 fulfilled
状态并且路由将继续。
不要忘记使用 conditional rendering 这样的东西,以免在路由等待数据时显示空白屏幕。
*:只要正在获取数据,这将阻止所有路由和导航。当心。
我所做的和对我来说很好的工作是将我的 Vue 实例 (new Vue({... })) 包装在 .then()“Promise”中。如果一切正常,这个 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
这样做将使处理获取的商店数据的路由守卫正常工作
希望对您有所帮助,如果我的英语不好,请见谅:)
自从第一次提出这个问题后,vue-router (v3.5.1) 已经公开了 check for the initial navigation 仅在第一条路线上执行这样的操作和 运行 的能力。
比较 from
与 VueRouter.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();
}
})
在我的应用程序中,我需要在路由开始之前将一些数据加载到 VueX 存储中(例如用户会话)。
竞争条件的示例如下:
// In routes definition
{
name: 'login',
path: '/login',
component: Login,
meta: {
goToIndexIf: () => store.getters['auth/loggedIn']
}
}
在这种情况下,路由守卫可能会在从服务器接收到用户之前执行。
使用条件渲染没有帮助,因为路由守卫在渲染模板中使用或不使用 <router-view v-if="storeReady">
执行。
如何让我的所有路由都等待一些异步数据?
解决方法很简单。在商店的相关部分添加 init
或等效的 Vuex action
。
它应该 return 您的应用程序 绝对需要的所有数据请求的 Promise
*:
init ({ dispatch }) { // Could also be async and use await instead of return
return Promise.all([
dispatch('getUserSession'), // Using another <b>action</b>
dispatch('auth/init'), // In another module
fetch('tehKittenz') // With the native <b>fetch</b> API
// ...
])
}
以上代码可以使用任何 return 是 Promise
。
然后只需使用 beforeEach
在您的路由器中创建一个 global navigation guard。
这个守卫将等待 dispatch
对商店产生的承诺。
// In your router initialization code
const storeInit = store.dispatch('init')
// Before <b>all other beforeEach</b>
router.beforeEach((to, from, next) => {
storeInit.then(next)
.catch(e => {
// Handle error
})
})
这样,如果路由发生在商店完全加载之前,路由器将简单地等待。
如果之后发生路由,promise 将已经处于 fulfilled
状态并且路由将继续。
不要忘记使用 conditional rendering 这样的东西,以免在路由等待数据时显示空白屏幕。
*:只要正在获取数据,这将阻止所有路由和导航。当心。
我所做的和对我来说很好的工作是将我的 Vue 实例 (new Vue({... })) 包装在 .then()“Promise”中。如果一切正常,这个 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
这样做将使处理获取的商店数据的路由守卫正常工作
希望对您有所帮助,如果我的英语不好,请见谅:)
自从第一次提出这个问题后,vue-router (v3.5.1) 已经公开了 check for the initial navigation 仅在第一条路线上执行这样的操作和 运行 的能力。
比较 from
与 VueRouter.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();
}
})