带有firebase身份验证的vue路由器错误

Posted

技术标签:

【中文标题】带有firebase身份验证的vue路由器错误【英文标题】:vue router error with firebase auth 【发布时间】:2018-04-13 09:13:09 【问题描述】:

我尝试使用 vue.js 和 firebase 进行身份验证。

并且发生错误 router.beforeEach 函数, 有人知道为什么会发生这种情况吗?

控制台错误

vue-router.esm.js?fe87:16 [vue-router] 路由导航期间未捕获的错误: 警告@ vue-router.esm.js?fe87:16 中止@vue-router.esm.js?fe87:1904 迭代器@vue-router.esm.js?fe87:1968 步@vue-router.esm.js?fe87:1717 runQueue@vue-router.esm.js?fe87:1725 confirmTransition@vue-router.esm.js?fe87:1972 transitionTo @ vue-router.esm.js?fe87:1874 推@vue-router.esm.js?fe87:2181 (匿名)@ vue-router.esm.js?fe87:1960 (匿名)@ index.js?3672:44

路由器/index.js

import Vue from 'vue'
import Router from 'vue-router'
import addPost from '@/components/addPost'
import showPost from '@/components/showPost'
import Login from '@/components/Login'
import SignUp from '@/components/SignUp'
import firebase from 'firebase'


Vue.use(Router)

const router = new Router(
    mode: 'history',
  routes: [
    
      path: '/',
      name: 'app',
      component: showPost
    ,
    
      path: '/add',
      component: addPost,
      meta: 
        requiresAuth: true
      
    ,
    
        path: '/login',
        name: 'Login',
        component: Login
    ,
    
        path: '/signup',
        name: 'SignUp',
        component: SignUp
    
  ]
)

router.beforeEach((to, from, next) => 
  let currentUser = firebase.auth().currentUser;
  let requiresAuth = to.matched.some(record => record.meta.requiresAuth);

  if (requiresAuth && !currentUser) next('/login')
  else if (!requiresAuth && currentUser) next('/')
  else next()
)


export default router

main.js

import Vue from 'vue'
import App from './App'
import router from './router'
import VueFire from 'vuefire'
import firebase from 'firebase'

Vue.use(VueFire)

Vue.config.productionTip = false

let app;

firebase.auth().onAuthStateChanged(function(user) 

    if(!app) 
        app = new Vue(
          el: '#app',
          router,
          template: '<App/>',
          components:  App 
        )
    

)

App.vue

<template>
  <div id="app">
    <app-header></app-header>
    <router-view></router-view>
    <button @click="logout">Logout</button>
  </div>
</template>

<script>
import header from './components/header'
import firebase from 'firebase'

export default 
  name: 'app',
  components: 
     'app-header': header
  ,
  methods: 
    logout: function() 
      firebase.auth().signOut().then(() => 
        this.$router.replace('login')
      )
    
  


</script>

登录.vue

import firebase from 'firebase'

import db from '../firebaseInit'
const postRef = db.ref('posts')

export default 
  name: 'login',
  data: function() 
    return 
      email: '',
      password: ''
    
  ,
  methods: 
    signIn: function() 
      firebase.auth().signInWithEmailAndPassword(this.email, this.password).then(
        (user) => 
          this.$router.replace('/')
        ,
        (err) => 
          alert('Oops ' + err.message)
        
      );
    
  

</script>

addPost.vue

<template>
  <div id="add-blog">
      <h2>Add a New Post</h2>
      <form v-if="!submitted">
        <label>Title:</label>
        <input type="text" v-model="newPost.title" required />
        <p> getDate </p>
        <label for="">Content:</label>
        <textarea v-model.trim="newPost.content"></textarea>
        <div id="checkboxes">
          <p>Categories:</p>
          <label>Vue.js</label>
          <input type="checkbox" value="vue" v-model="newPost.categories" />
          <label>CSS Magic</label>
          <input type="checkbox" value="css" v-model="newPost.categories" />
        </div>
        <label>Author:</label>
        <select v-model="newPost.author">
          <option v-for="author in authors"> author </option>
        </select>
        <button @click.prevent="addPost">Add Post</button>
      </form>
      <div v-if="submitted">
        <p>Congraturation!</p>
      </div>
      <div id="preview">
        <h3>Preview Post</h3>
        <h4>Title  newPost.title </h4>
        <h4>Content </h4>
        <p style="white-space: pre"> newPost.content </p>
        <ul>
          <li v-for="category in newPost.categories"> category </li>
        </ul>
        <p> newPost.author </p>
      </div>
    </div>
</template>

<script>

import db from '../firebaseInit'
const postRef = db.ref('posts')

export default 
  data() 
    return 
      newPost: 
        date: '',
        title: '',
        author: '',
        content: '',
        categories: []
      ,
      authors: ['Naeun', 'Raphael'],
      submitted: false,
      items: []
    
  ,
  methods: 
    addPost: function() 
      postRef.push(this.newPost)
      this.newPost.date = '',
      this.newPost.title = '',
      this.newPost.author = '',
      this.newPost.content = '',
      this.newPost.categories = ''
    ,
    removePost: function() 
      postRef.child(post['.key']).remove()
    
  ,
  computed: 
    getDate: function() 
      const toTwoDigits = num => num < 10 ? '0' + num : num;
      let today = new Date();
      let year = today.getFullYear();
      let month = toTwoDigits(today.getMonth() + 1);
      let day = toTwoDigits(today.getDate());
      return this.newPost.date = `$year-$month-$day`;
    
  


</script>

【问题讨论】:

【参考方案1】:

确保在通过导航守卫的任何给定传递中,下一个函数只被调用一次。它可以出现多次,但前提是逻辑路径没有重叠,否则钩子永远不会被解析或产生错误。

你的 else if 条件 else if (!requiresAuth &amp;&amp; currentUser) next('/') 违反了这条规则。

改变你的路由保护逻辑

// check if route requiresAuth
router.beforeEach((to, from, next) => 
  if (to.matched.some(rec => rec.meta.requiresAuth)) 
    const user = firebase.auth().currentUser;
    // check auth state of user
    user ? next() : next('/login') // user not signed in, route to login
   else 
    next(); // route does not require auth
  
);

https://router.vuejs.org/guide/advanced/navigation-guards.html#global-before-guards

希望这会有所帮助。

【讨论】:

以上是关于带有firebase身份验证的vue路由器错误的主要内容,如果未能解决你的问题,请参考以下文章

必须点击登录按钮两次;使用 vue-router 和 firebase 身份验证

如果用户已经使用 Vue 和 Firebase 身份验证登录,如何自动重定向用户?

Firebase 身份验证。更新所有项目文件

使用 Vue.js 的 Firebase 电话号码身份验证不起作用

Vue.js:如何保护登录组件免受经过身份验证的用户的影响

Vue.js 路由在身份验证检查后重定向之前短暂显示 404 错误消息