简体   繁体   中英

Vue router guard triplicating navigation

I have a router guard beforeEach route to watch if there's user authenticated:

import Vue from "vue";
import VueRouter from "vue-router"
import Login from "../views/Login.vue"
import Home from "../components/Home.vue"
import Register from "../views/Register.vue"
import Dashboard from "../views/Dashboard.vue"
import Pricing from "../components/Pricing.vue"
import Invoices from "../components/Invoices.vue"
import { FirebaseAuth } from "../firebase/firebase"

Vue.use(VueRouter);

const routes = [
  {
    path: "*",
    redirect: "/login",
  },
  {
    path: "/dashboard",
    name: "dashboard",
    component: Dashboard,
    children: [
      {
        path: "home",
        name: "home",
        component: Home,
      },
      {
        path: "pricing",
        name: "pricing",
        component: Pricing,
      },
      {
        path: "invoices",
        name: "invoices",
        component: Invoices,
      }
    ],
    meta: {
      auth: true,
    },
    redirect: "home"
  },
  {
    path: "/login",
    name: "login",
    component: Login,
  },
  {
    path: "/register",
    name: "register",
    component: Register,
  }
];

const router = new VueRouter({
  mode: "history",
  base: process.env.BASE_URL,
  routes
});


router.beforeEach((to, from, next)=>{
  let user = FirebaseAuth.currentUser;
  let auth = to.matched.some(record => record.meta.auth);
  
  if (auth && !user) {

    next('/login');

  } else if (!auth && user) {

    next('/dashboard/home');

  } else{

    next();

  }
});

export default router;

When I perform logouts and logins there's an error about redundant navigation, however, I just assumed that it's ok if I just catch this.$router.push('/dashboard/home').catch(err => err); and move on without the console.log err. But creating an alert on component created() I've noticed that the thing is just more serious than what I thought, the component that shows the alert on created() it's showing it three times, and as I have a fetch for restore items on created() , that function is being triggered three times which is obviously not the performance wanted.

  async created() {
    alert("created")
    this.credits = await fetchCredits(this.$firestore, this.$auth.currentUser);
    let role = await getCustomClaimRole(this.$auth.currentUser);
    this.subscription = role
      ? role.charAt(0).toUpperCase() + role.slice(1) + " " + "plan"
      : "You haven't subscribed yet";
    this.isLoading();
  },

inside fetchCredits() is the console.log triggering three times

export const fetchCredits = async function (firestore, currentUser) {
    // firestore collection of customers
    const db = firestore.collection("customers");
    /**
     * Let's fetch the credits from the user:
     */
    const credits = (await db.doc(currentUser.uid).get()).data();
    if (credits !== "undefined") {
        console.log(credits);
        return credits.credits
    } else {
        return 0;
    }
}

I think the problem is with the navigation guard, however, correct me if I'm wrong, but how to solve this?

I think that it has something to do with your router path:

  {
    path: "*",
    redirect: "/login",
  },

I have used Vue Router several times, but since I hadn't used wildcards before, I built a simplified Vue 2 CLI test application.

My router:

import Vue from 'vue'
import VueRouter from 'vue-router'

Vue.use(VueRouter)

import Home from '@/components/stackoverflow/router-wildcard-match/Home'
import RouteOne from '@/components/stackoverflow/router-wildcard-match/RouteOne'
import RouteTwo from '@/components/stackoverflow/router-wildcard-match/RouteTwo'
import WildCard from '@/components/stackoverflow/router-wildcard-match/WildCard'

const routes = [
  {
    path: '/*',
    name: 'wildcard',
    component: WildCard
  },
  {
    path: '/home',
    name: 'home',
    component: Home,
  },
  {
    path: '/routeone',
    name: 'routeOne',
    component: RouteOne,
  },
  {
    path: '/routetwo',
    name: 'routeTwo',
    component: RouteTwo,
  },
]

export default new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes
})

and my navbar component that routes programmatically:

<template>
  <div class="navbar-sandbox">
    <nav class="navbar navbar-expand-md navbar-light bg-light">
      <ul class="navbar-nav mr-auto">
        <li class="nav-item active">
          <a class="nav-link" href="#" @click.prevent="navigate('home')">Home</a>
        </li>
        <li class="nav-item">
          <a class="nav-link" href="#" @click.prevent="navigate('routeone')">RouteOne</a>
        </li>
        <li class="nav-item">
          <a class="nav-link" href="#" @click.prevent="navigate('routetwo')">RouteTwo</a>
        </li>
      </ul>
    </nav>
  </div>
</template>

<script>
  export default {
    data() {
      return {
        //currentRoute: 'home',
        currentPath: 'home'
      }
    },
    methods: {
      // NOTE: Using route names work regardless of having wildcard path
      // navigate(route) {
      //   if (route !== this.currentRoute) {
      //     this.currentRoute = route;
      //     this.$router.push({ name: route });
      //   }
      // },
      navigate(path) {
        if (path !== this.currentPath) {
          this.currentPath = path;
          this.$router.push({ path: path });
        }
      }
    }
  }
</script>

As you can see in my code comments, when I programmatically route via the route names, it works even with having a wildcard path, but when I route via the actual route path, the routes are all intercepted by the wildcard.

My wildcard path is a bit different that yours, /* vs * .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM