我在用户的仪表板上有一个导航卫士,它需要用户存在才能继续。
export default new Router({
routes: [
{
path: '/',
name: 'home',
component: Home
},
{
path: '/dashboard',
name: 'dashboard',
component: Dashboard,
beforeEnter: (to, from, next) => {
const user = JSON.parse(store.state.authenticatedUser)
if(user) {
console.log("Route accepted.")
next()
} else {
console.log("Route rejected.")
next('/')
}
}
}
]
})
在我的登录表单上,我分派了获取令牌,该令牌返回令牌和关联的用户。
<template>
<v-container>
<h1 class="display-2">Login</h1>
<v-form
ref="form"
v-model="valid"
lazy-validation
>
<v-col cols="12" md="12">
<v-row align="center">
<v-text-field
v-model="email"
:rules=emailRules
label="Email"
required
dense
></v-text-field>
</v-row>
<v-row align="center">
<v-text-field
v-model="password"
label="Password"
required
dense
type="password"
></v-text-field>
</v-row>
</v-col>
<v-btn
@click="login"
>Login</v-btn>
</v-form>
</v-container>
</template>
<script>
export default {
data: () => ({
valid: true,
password: '',
email: '',
emailRules: [
v => !!v || 'Email is required.',
v => /.+@.+\..+/.test(v) || 'You have entered an invalid email.',
],
}),
methods: {
login() {
this.$store.dispatch('obtainToken', { email: this.email, password: this.password })
this.$router.push('dashboard')
}
}
}
</script>
actions: {
logout() {
this.commit('revokeUser')
this.commit('revokeToken')
},
obtainToken(random, payload) {
const data = {
email: payload.email,
password: payload.password
}
api.post(this.state.endpoints.obtainToken, data)
.then((response => {
this.commit('updateSessionUser', response.data.user)
this.commit('updateToken', response.data.token)
}))
.catch((e) => {
console.log(e)
})
},
单击submit
时,会获得用户,但由于当时不存在用户,因此路由被拒绝。我必须再次单击submit
,这将允许用户访问dashboard
路由。
所以我可以从输出中收集到,$router.push
的发生与obtainToken
的发生有关,因此它们竞争。第二次登录时已有用户在场,因此继续进行。我在这里做什么错了?
我也尽力做到这一点,所以将router.push()也称为对诺言的解决方案。
login() {
this.$store.dispatch('obtainToken', { email: this.email, password: this.password })
.then(() =>
this.$router.push('dashboard')
)
}
答案 0 :(得分:2)
问题似乎出在login
方法中。
login() {
this.$store.dispatch('obtainToken', { email: this.email, password: this.password })
this.$router.push('dashboard')
}
将同时运行两个呼叫。尝试在获取令牌调用的结果之前导航用户。
login() {
this.$store.dispatch('obtainToken', { email: this.email, password: this.password })
.then(() =>
this.$router.push('dashboard')
)
}
一旦令牌存在,就可以在导航到仪表板时从状态中获取令牌。
答案 1 :(得分:1)
呼叫dispatch
是异步的。
更改路由器时,它尚未定义。
因此,您需要先在mounted()
中调用dispatch,然后才能移动另一页。
mounted() {
this.$store.dispatch('obtainToken', { email: this.email, password: this.password })
},
methods: {
login() {
this.$router.push('dashboard')
}
}
或
methods: {
login() {
this.$store.dispatch('obtainToken', { email: this.email, password: this.password }).then(() => this.$router.push('dashboard'))
}
}
编辑:您需要像下面这样在promise
中返回obtainToken
;
obtainToken(random, payload) {
...
return api.post(this.state.endpoints.obtainToken, data) // just add `return`
...
}