解决Vue报错:Uncaught (in promise) NavigationDuplicated: Avoided redundant navigation to current location

一、重复点击导航时,控制台出现报错 

解决方案:

 方案一:只需在 router 文件夹下,添加如下代码:
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '@/views/Home'
import Main from '@/views/Main'
import User from '@/views/User'
Vue.use(VueRouter)
 
// 0. 如果使用模块化机制编程,导入Vue和VueRouter,要调用 Vue.use(VueRouter)
// 1. 定义 (路由) 组件。
// 可以从其他文件 import 进来
 
// 2. 定义路由
// 每个路由应该映射一个组件。 其中"component" 可以是
// 通过 Vue.extend() 创建的组件构造器,
// 或者,只是一个组件配置对象。
// 我们晚点再讨论嵌套路由。
const routes = [
  // //主路由
  {
    path: '/',
    component: Main,
    redirect:"home",
    children: [//子路由,嵌套路由
      {
        path: 'home',
        component: Home
      },
      {
        path: 'user',
        component: User
      },
      {
        path: "/acl/user",
        name: "user",
        title: "用户管理",
        icon: "setting",
        component: () => import("@/views/acl/user/List.vue"),
      },
      {
        path: "/acl/role",
        name: "role",
        title: "角色管理",
        icon: "setting",
        component: () => import("@/views/acl/role/List.vue"),
      },
      {
        path: "/acl/menu",
        name: "menu",
        title: "菜单管理",
        icon: "setting",
        component: () => import("@/views/acl/menu/List.vue"),
      }
      // ,
      // {
      //   title: "权限管理",
      //   icon: "s-order",
      //   name: "/acl",
      //   path: '/acl',
      //   children: [
      //     {
      //       path: "/user1",
      //       name: "user",
      //       title: "用户管理",
      //       icon: "setting",
      //       component: () => import("@/views/acl/user/List.vue"),
      //     },
      //     {
      //       path: "/acl/role",
      //       name: "role",
      //       title: "角色管理",
      //       icon: "setting",
      //       component: () => import("@/views/acl/role/List.vue"),
      //     },
      //     {
      //       path: "/acl/menu",
      //       name: "menu",
      //       title: "菜单管理",
      //       icon: "setting",
      //       component: () => import("@/views/acl/menu/List.vue"),
      //     },
      //   ],
      // },
    ]
  },
 
 
 
]
 
// 3. 创建 router 实例,然后传 `routes` 配置
// 你还可以传别的配置参数, 不过先这么简单着吧。
const router = new VueRouter({
  routes // (缩写) 相当于 routes: routes
})
 
// 4. 创建和挂载根实例。(在main.js里继续挂载)
// 记得要通过 router 配置参数注入路由,
// 从而让整个应用都有路由功能
 
// 解决重复点击导航时,控制台出现报错
const VueRouterPush = VueRouter.prototype.push
VueRouter.prototype.push = function push (to) {
  return VueRouterPush.call(this, to).catch(err => err)
}
 
export default router

方案二 :  使用 catch 方法捕获 router.push 异常。 
this.$router.push(route).catch(err => {
  console.log('输出报错',err)
})

 方案三   :在跳转时,判断是否跳转路由和当前路由是否一致,避免重复跳转产生问题。
index路由文件
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '@/views/Home'
import Main from '@/views/Main'
import User from '@/views/User'
Vue.use(VueRouter)
 
// 0. 如果使用模块化机制编程,导入Vue和VueRouter,要调用 Vue.use(VueRouter)
// 1. 定义 (路由) 组件。
// 可以从其他文件 import 进来
 
// 2. 定义路由
// 每个路由应该映射一个组件。 其中"component" 可以是
// 通过 Vue.extend() 创建的组件构造器,
// 或者,只是一个组件配置对象。
// 我们晚点再讨论嵌套路由。
const routes = [
  // //主路由
  {
    path: '/',
    component: Main,
    redirect:"home",
    children: [//子路由,嵌套路由
      {
        path: 'home',
        component: Home
      },
      {
        path: 'user',
        component: User
      },
      {
        path: "/acl/user",
        name: "user",
        title: "用户管理",
        icon: "setting",
        component: () => import("@/views/acl/user/List.vue"),
      },
      {
        path: "/acl/role",
        name: "role",
        title: "角色管理",
        icon: "setting",
        component: () => import("@/views/acl/role/List.vue"),
      },
      {
        path: "/acl/menu",
        name: "menu",
        title: "菜单管理",
        icon: "setting",
        component: () => import("@/views/acl/menu/List.vue"),
      }
      // ,
      // {
      //   title: "权限管理",
      //   icon: "s-order",
      //   name: "/acl",
      //   path: '/acl',
      //   children: [
      //     {
      //       path: "/user1",
      //       name: "user",
      //       title: "用户管理",
      //       icon: "setting",
      //       component: () => import("@/views/acl/user/List.vue"),
      //     },
      //     {
      //       path: "/acl/role",
      //       name: "role",
      //       title: "角色管理",
      //       icon: "setting",
      //       component: () => import("@/views/acl/role/List.vue"),
      //     },
      //     {
      //       path: "/acl/menu",
      //       name: "menu",
      //       title: "菜单管理",
      //       icon: "setting",
      //       component: () => import("@/views/acl/menu/List.vue"),
      //     },
      //   ],
      // },
    ]
  },
 
 
 
]
 
// 3. 创建 router 实例,然后传 `routes` 配置
// 你还可以传别的配置参数, 不过先这么简单着吧。
const router = new VueRouter({
  routes // (缩写) 相当于 routes: routes
})
 
// 4. 创建和挂载根实例。(在main.js里继续挂载)
// 记得要通过 router 配置参数注入路由,
// 从而让整个应用都有路由功能
 
// 解决重复点击导航时,控制台出现报错
// const VueRouterPush = VueRouter.prototype.push
// VueRouter.prototype.push = function push (to) {
//   return VueRouterPush.call(this, to).catch(err => err)
// }
 
export default router

 菜单组件
<template>
  <div class="hello">
    <!-- <el-radio-group v-model="isCollapse" style="margin-bottom: 20px">
      <el-radio-button :label="false">展开</el-radio-button>
      <el-radio-button :label="true">收起</el-radio-button>
    </el-radio-group> -->
 
    <el-menu
      default-active="1-4-1"
      class="el-menu-vertical-demo"
      @open="handleOpen"
      @close="handleClose"
      :collapse="isCollapse"
      background-color="#545c64"
      text-color="#fff"
      active-text-color="#ffd04b"
    >
      <!-- 循环菜单数据 -->
      <label v-for="item in menuData" :key="item.name">
        <!-- 判断是否有子菜单,如果有就创建submenu,没有就创建menu-item -->
        <el-submenu
          :index="item.name"
          v-if="item.children"
          @click="clickMenu(item)"
        >
          <template slot="title">
            <i :class="`el-icon-${item.icon}`"></i>
            <span>{{ item.title }}</span>
          </template>
          <label>
            <!-- 自己调用自己 -->
            <CommonAsideMenuTRee
              :menuData="item.children"
            ></CommonAsideMenuTRee>
          </label>
        </el-submenu>
        <el-menu-item v-else :index="item.name" @click="clickMenu(item)">
          <template slot="title">
            <i :class="`el-icon-${item.icon}`"></i>
            <span>{{ item.title }}</span>
          </template>
        </el-menu-item>
      </label>
      <!-- <el-menu-item
        v-for="item in noChildren"
        :key="item.name"
        index="item.name"
      >
        <i :class="`el-icon-${item.icon}`"></i>
        <span slot="title">{{ item.label }}</span>
      </el-menu-item>
 
      <el-submenu
        v-for="item in hasChildren"
        :key="item.name"
        index="item.name"
      >
        <template slot="title">
          <i :class="`el-icon-${item.icon}`"></i>
          <span slot="title">{{ item.label }}</span>
        </template>
        <el-menu-item-group v-for="child in item.children" :key="child.name">
          <el-menu-item index="child.name">{{ child.label }}</el-menu-item>
        </el-menu-item-group>
      </el-submenu>   -->
    </el-menu>
  </div>
</template>
 
<script>
import CommonAsideMenuTRee from "@/components/CommonAsideMenuTRee.vue";
export default {
  name: "CommonAsideMenuTRee",
  components: {
    CommonAsideMenuTRee,
  },
  props: {
    menuData: {
      type: Array,
    },
  },
  data() {
    return {
      isCollapse: false,
      menuList1: [
        {
          path: "/user",
          name: "user",
          label: "用户管理",
          icon: "user",
          url: "UserManage/UserManage",
        },
        {
          path: "/",
          name: "Main",
          label: "首页",
          icon: "s-home",
          url: "Main/Main",
        },
        {
          label: "权限管理",
          icon: "s-order",
          name: "acl",
          component: "",
          path: "",
          children: [
            {
              path: "/acl/user",
              name: "user",
              label: "用户管理",
              icon: "setting",
              component: () => import("@/views/acl/user/List.vue"),
            },
            {
              path: "/acl/role",
              name: "role",
              label: "角色管理",
              icon: "setting",
              component: () => import("@/views/acl/role/List.vue"),
            },
            {
              path: "/acl/menu",
              name: "menu",
              label: "菜单管理",
              icon: "setting",
              component: () => import("@/views/acl/menu/List.vue"),
            },
          ],
        },
      ],
    };
  },
  computed: {
    //没有子菜单
    noChildren() {
      return this.menuList.filter((item) => !item.children);
    },
    //有子菜单
    hasChildren() {
      return this.menuList.filter((item) => {
        return item.children;
      });
    },
  },
  methods: {
    handleOpen(key, keyPath) {
      console.log(key, keyPath);
    },
    handleClose(key, keyPath) {
      console.log(key, keyPath);
    },
    //点击菜单,路由跳转
    clickMenu(item) {
      console.log("this.$route.path ==== " +this.$route.path);
      console.log("item.path =========== "+ item.path);
      console.log("-------------------------------------------------");
      // 判断是否跳转路由和当前路由是否一致,避免重复跳转产生问题
      // 当页面的路由和跳转的路由不一致才跳转
      if(this.$route.path !== item.path && !(this.$route.path === '/home' && item.path === '/')){
        this.$router.push(item.path)
      }
  
    },
  },
};
</script>
 
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style lang="less" scoped>
.el-menu {
  // height: 100vh;
  border-right: none;
}
</style>

 

在使用Vue.js框架开发单页面应用(SPA)时,我们可能会遇到一个错误提示:"Uncaught (in promise) NavigationDuplicated: Avoided redundant navigation to current location"。这个错误通常发生在使用Vue Router进行路由跳转时,尝试导航到一个已经是当前激活路由的地址。 这个错误的原因是在某些情况下,比如在调用`router.push`或者`router.replace`方法时,如果目标路由是当前路由,就会触发这个警告。Vue Router默认情况下会阻止同一个路由的重复导航,以避免不必要的历史记录栈操作和重复渲染组件,这有助于防止可能的无限循环或者性能问题。 为了处理这个错误,可以采取以下几种方法: 1. 使用`router.go()`或`router.back()`替代`router.push`或`router.replace`进行导航,因为前者处理浏览器历史记录,通常不会触发冗余导航警告。 2. 在进行路由跳转之前,可以先检查当前路由是否与目标路由相同,如果相同则不执行跳转操作。 3.Vue Router的配置中,可以通过设置`scrollBehavior`为`false`来禁用滚动行为,可能会避免触发这个错误。 4.Vue实例或组件中,可以通过捕获路由的`NavigationDuplicated`错误来避免它影响应用的其他部分。 示例代码: ```javascript // 在Vue实例或组件中处理路由跳转 this.$router.push('/about').catch(err => { if (err.name !== 'NavigationDuplicated') { console.error(err); // 打印非重复导航错误 } }); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值