Vuex商店/导航防护功能第一次无法使用

时间:2019-10-13 04:53:57

标签: javascript vue.js vuex vue-router

我在用户的仪表板上有一个导航卫士,它需要​​用户存在才能继续。

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路由。

enter image description here

所以我可以从输出中收集到,$router.push的发生与obtainToken的发生有关,因此它们竞争。第二次登录时已有用户在场,因此继续进行。我在这里做什么错了?


我也尽力做到这一点,所以将router.push()也称为对诺言的解决方案。

login() {
      this.$store.dispatch('obtainToken', { email: this.email, password: this.password })
      .then(() =>
           this.$router.push('dashboard')
      )
}

2 个答案:

答案 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`
  ...
}