欢迎光临
我们一直在努力

vue 路由 NavigationDupLicated 解决,vue编程式路由产生冗余导航,vue-router报错问题解决

首先看一下声明式导航与编程式导航

声明式导航:

声明式导航是写在template标签里,通过<router-link></router-link>标签来触发:

   <router-link to="/about">跳转</router-link>

编程式导航:

编程式导航是在js代码进行跳转的操作。使用this.$router.push(xxx)来触发跳转:

this.$router.push('path')
//传递参数
this.$router.push({
     path: 'path', query: {
     id: 1}})
this.$router.push({
     name: 'name', params: {
     id: 1}})

问题

编程式路由跳转到当前路由(参数不变),多次执行会抛出 NavigationDupLicated 的警告错误。声明式导航则不存在此问题,因为`vue-router`底层已经处理好了。
为什么编程式导航进行路由跳转的时候,就会有这种警告错误呢?因为 vue-router:3.5.3 版本引入了 promise,假如没有回调函数,错误信息就会交给全局的路由错误处理,因此就会报上述的错误。

解决方法

方法一 运用编程式路由的时候加上成功,失败的回调

this.$router.push(
  { name: "home", params: { id: 1 } },
  () => {}, // 成功回调
  () => {} //失败回调
);

方法二 重写 push,replace

方法一治标不治本,每次用编程式路由都要加成功失败回调
下面通过重写 push,replace 解决:
$routervueRouter 类的一个实例
push 方法在 vueRouterprototype

重写push

// 在路由index.js文件中
// 重写push
// 保存原有的push方法
const originalPush = VueRouter.prototype.push;
VueRouter.prototype.push = function (location, resolve, reject) {
  // 如果用户传递过来了成功失败回调
  // 调用原有push方法
  if (resolve && reject) {
    //这里要注意上下文中的this为vueRouter 这里如果直接调用 originalPush 中的this是window,我们要将this改为vueRouter,这时就要用this冒充call
    originalPush.call(this, location, resolve, reject);
  } else {
    // 用户没有传递成功失败回调,我们自动加上
    originalPush.call(this,location,() => {},() => {});
  }
};

重写replace

// 在路由index.js文件中
// 重写replace
// 保存原有的replace方法
const originalReplace = VueRouter.prototype.replace;
VueRouter.prototype.push = function (location, resolve, reject) {
  if (resolve && reject) {
    originalReplace.call(this, location, resolve, reject);
  } else {
    originalReplace.call(this,location,() => {},() => {});
  }
};

一个完整的 路由文件

src/router/index.js

// 该文件专门用于创建整个应用的路由器
// 引入vue路由
import VueRouter from "vue-router";
import routers from "./routers";
// 重写push和replace
let originPush = VueRouter.prototype.push;
let originReplace = VueRouter.prototype.push;
// push方式跳转路由(有痕)
VueRouter.prototype.push = function (location, resolve, reject) {
    if (resolve && reject) {
        originPush.call(this, location, resolve, reject);
    } else {
        originPush.call(this, location, () => {}, () => {});
    }
};
// replace方式跳转路由(无痕)
VueRouter.prototype.replace = function (location, resolve, reject) {
    if (resolve && reject) {
        originReplace.call(this, location, resolve, reject);
    } else {
        originReplace.call(this, location, () => {}, () => {});
    }
};
import store from "@/store";
//创建并暴露一个路由器
let router = new VueRouter({
    routes: routers,
    // 滚动行为
    scrollBehavior(to, from, savedPosion) {
        //返回的这个y=e,代表的滚动条在最上方
        return {y: 0};
    },
});
//全局守卫:前置守卫(在路由跳转之间进行判断)
router.beforeEach(async (to, from, next) => {
    // to and from are both route objects. must call `next`.
    //获取仓库中的token-----可以确定用户是登录了
    let token = store.state.user.token;
    let name = store.state.user.userInfo.name;
    //用户登录了
    if (token) {
        //已经登录而且还想去登录------不行
        if (to.path == "/login" || to.path == "/register") {
            next("/home");
        } else {
            //已经登陆了,访问的是非登录与注册
            //登录了且拥有用户信息放行
            if (name) {
                next();
            } else {
                //登陆了且没有用户信息
                //在路由跳转之前获取用户信息且放行
                try {
                    //获取用户信息
                    await store.dispatch("getUserInfo");
                    next();
                } catch (error) {
                    //token失效从新登录
                    //清除token
                    await store.dispatch("logout");
                    // 回到登录页
                    this.$router.push("/login");
                }
            }
        }
    } else {
        //未登录:不能去交易相关、不能去支付相关【pay|paysuccess】、不能去个人中心
        //未登录去上面这些路由-----登录
        let toPath = to.path;
        if (toPath.includes("/trade") || toPath.includes("/pay") || toPath.includes("/center")) {
            //把未登录的时候向去而没有去成的信息,存储于地址栏中【路由】
            next("/login?redirect=" + toPath);
            // console.log(toPath);
        } else {
            //去的不是上面这些路由(home|search|shopCart)---放行
            next();
        }
    }
});
export default router;

src/router/routers.js

export default [
    {
        path: "/paySuccess",
        component: () =>
            import ("@/pagaes/PaySuccess"),
        meta: {
            show: true,
        },
    },
]
赞(1)
版权归原作者所有,如有侵权请告知。达维营-前端网 » vue 路由 NavigationDupLicated 解决,vue编程式路由产生冗余导航,vue-router报错问题解决

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址