如何通过商店操作以异步方式检索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
}
}
}
这对于第一页加载或页面重新加载,获取init数据以及路由器需要等待该数据以允许用户访问该页面时,这一点尤为重要。
路由器是否可以等待"要获取的数据? 或者什么是与异步vuex商店数据结合处理导航防护的最佳方式?
(哦,预先填充" asyncData"不能成为解决方案,因为beforeEnter挂钩需要根据数据库做出真实数据,而不是默认数据)
答案 0 :(得分:11)
您可以通过从vuex操作返回承诺来执行此操作,因为它已解释为here并从beforeEnter
内部调用调度。
代码应如下所示:
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
})
}
}
答案 1 :(得分:7)
您是否真的需要在每次路由更改之前从服务器异步获取数据,或者您是否只需要保留商店中的某些数据,以便在重新加载页面或用户使用时不会“消失”直接链接?
如果是后一种情况,您可以将身份验证数据(例如JWT令牌)保存在localStorage / cookie 中,然后在初始化期间将它们从存储中拉出(并将它们提交到存储) - 这应该是一个同步动作。
您还可以使用vuex-persistedstate 保留商店的整个州,以便在重新加载时不会消失,也不需要保持水分。
如果您需要在首次加载或页面重新加载之前异步获取某些数据,您可以调度存储操作并在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');
});
答案 2 :(得分:5)
我通过使用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,
}
]
})