vue3动态路由到底如何实现vue-router4中addRoutes失效?

本文介绍了在Vue3中如何使用`addRoute`函数实现动态路由加载,并结合角色权限和菜单路由管理,包括使用`toTree`方法将菜单结构转换为树状结构,以及路由守卫的逻辑处理。
摘要由CSDN通过智能技术生成

大家都知道,后台管理系统中,避不开的一个问题,就是角色权限,那么权限这块必然跟菜单路由关联。vue2中可以通过addRoutes函数,实现动态路由,那么vue3怎么实现呢

1.router.ts

vue3中使用addRoute方法可以实现,动态路由的加载

import { createRouter, createWebHashHistory, RouteRecordRaw } from "vue-router";
import { toTree } from "@/utils/tools";
import NProgress from "nprogress";
//NProgress:路由加载过渡动画
import { accountStore } from "@/store/index";
import { api_info } from "@/api/webPage";
import LocalStorage from "@/utils/localStorage";

const routes: Array<RouteRecordRaw> = [
  {
    path: "/",
    name: "webPage", //展示页
    component: () => import("@/views/webPage/index.vue"),
    meta: { name: "主页" },
  },
  {
    path: "/admin",
    name: "admin",
    meta: { name: "layout" },
    component: () => import("@/views/layout/index.vue"),
    children: [
      {
        path: "/home",
        name: "首页", //展示页
        component: () => import("@/views/home/index.vue"),
        meta: { name: "主页" },
      },
      {
        path: "/personalCenter",
        name: "个人中心",
        component: () => import("@/views/personalCenter/index.vue"),
        meta: { name: "个人中心" },
      },
    ],
  },
  {
    path: "/:catchAll(.*)",
    name: "404",
    component: () => import("@/views/error/index.vue"),
  },
];

const router = createRouter({
  history: createWebHashHistory(),
  routes,
});
/**导入路由对应菜单 */
function view(path: any) {
  let modules = import.meta.glob("../views/**/*.vue");
  return modules[`../views/${path}/index.vue`];
}
/**变成路由结构 */
function setRouters(params: any) {
  let newRouter = params.map((r: any) => {
    r.components = r.components.replace(/^\//g, "");
    let route: any = {
      path: r.path,
      name: r.menuName,
      component: view(r.components),
      meta: {
        type: r.type, // 1菜单 2目录 3 按钮
        icon: r.icon, //图标
        status: r.status, //是否显示
      },
    };
    if (r.children) {
      route.children = setRouters(r.children);
    }
    return route;
  });
  return newRouter;
}

let flag = false; //是否刷新过菜单
const whiteList = ["/"]; //白名单
/**路由守卫 */
router.beforeEach(async (to: any, from: any, next) => {
  /**如果2次去的相同页面,不加载路由动画(针对于退出登录的) */
  if (to.path !== from.path) {
    NProgress.start();
  }
  const myAccountStore = accountStore();
  let userId = myAccountStore.$state.userId;//获取userId
  let token = LocalStorage.get("rmtk_token");//获取token
  //如果去白名单,就放行
  if (whiteList.indexOf(to.path) !== -1) {
    next();
  } else {
    /**如果登录有userId和token,并且,没有加载过菜单。那就发起请求,获取用户菜单 */
    if (!flag && userId && token) {
      flag = true;
      let res: any = await api_info({ userId }); //发起用户信息接口,获取token
      if (res.code === 200) {
        myAccountStore.setUserInfo(res.data);
      } else if (res.code === 201) {
        myAccountStore.setUserInfo(res.data);
      }
      /**变成树状 */
      let userRouter = toTree(myAccountStore.$state.userRouter); //变成树状
      /**变成路由结构 */
      userRouter = setRouters(userRouter);
      /**找到后台首页 */
      router.options.routes.forEach((o: any) => {
        if (o.name === "admin" || o.path === "/admin") {
          userRouter.forEach((element: any) => {
            /**添加路由到首页 */
            router.addRoute("admin", element);
            o.children.push(element);
          });
        }
      });
      next({ path: to.path });
    } else {
      //如果没有 userId ||  token就去登录
      if (!userId || !token) {
        next("/"); //本项目 '/'为登录页面
      } else {
        //如果有 userId ||  token放行
        next(); //放行
      }
    }
  }
});
router.afterEach(() => {
  NProgress.done();//结束路由加载动画
});
export default router;
2.toTree.js(@/utils/tools)文件方法
export function toTree(arr: any) {
  let map: any = {}; // 用于快速查找节点
  let tree: any = []; // 最终的树形数组
  // 先对原始数组进行遍历,为其添加一个指向其子节点的引用
  for (let i = 0; i < arr.length; i++) {
    let node = arr[i];
    map[node.id] = {
      ...node,
      children: [],
      parentName: "",
      hasChildren: null,
    };
  }
  // 再遍历一次原始数组,为每个节点添加子节点
  for (let i = 0; i < arr.length; i++) {
    let node = arr[i];
    if (node.parentId !== null) {
      // 如果节点有父ID,则找到父节点,并将当前节点添加为其子节点
      if (map[node.parentId]) {
        map[node.parentId].children.push({
          ...map[node.id],
          parentName: map[node.parentId].menuName,
        });
      } else {
        tree.push(map[node.id]);
      }
    } else {
      // 如果节点没有父ID,则直接添加到树形数组中
      tree.push(map[node.id]);
    }
  }

  /**设置有子级字段 */
  function setHasChildren(tree: any) {
    if (tree.length) {
      tree.forEach((e: any) => {
        if (e.children) {
          setHasChildren(e.children);
        }
        e.hasChildren = e.children.length ? true : false;
      });
    }
  }

  setHasChildren(tree);
  return tree;
}
3.补充:vue3退出登录,重置路由方法
  /**退出登录 */
    async function logOutHandler() {
      await router.replace({ path: "/" });//此处可能为异步,所以用await,变成同步
      await this.resetStore();//重置pinia
      LocalStorage.clear();//清除缓存
      location.reload();//刷新页面
    }

以上是vue3实现动态路由的代码,欢迎大家补充。总结:vue3使用addRoute可以实现动态路由

  • 21
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue动态路由刷新可以通过以下步骤来解决: 1. 首先,在Vue路由配置文件,定义一个空数组来存储需要动态添加的路由。 2. 在需要动态添加路由的地方,使用addRoutes方法来添加路由。这个方法接收一个路由配置的数组作为参数。 3. 为了解决刷新页面后动态路由重复添加的问题,可以在路由的addRoute方法使用router.matcher来进行处理。router.matcher是Vue Router内部用来匹配路由的方法。 举个例子,假设我们有一个需要动态添加的路由数据数组,可以按照以下步骤来实现动态路由刷新: 1. 首先,定义一个空数组来存储需要动态添加的路由: ``` const dynamicRoutes = []; ``` 2. 在需要动态添加路由的地方,使用addRoutes方法来添加路由。假设我们有一个路由数据数组叫做newRoutes: ``` router.addRoutes(newRoutes); ``` 3. 最关键的一步是解决刷新页面后动态路由重复添加的问题。可以通过在路由的addRoute方法使用router.matcher来进行处理: ``` const newRouter = new VueRouter({ mode: 'history', base: process.env.BASE_URL, routes: dynamicRoutes }); router.matcher = newRouter.matcher; ``` 通过以上步骤,我们就可以实现Vue动态添加路由并解决刷新页面后动态路由重复添加的问题。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [vue 解决addRoutes动态添加路由后刷新失效问题](https://download.csdn.net/download/weixin_38687807/12757832)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [vue解决动态路由加载,刷新页面出现路由重复添加/出现空白页的问题](https://blog.csdn.net/hahaha_1314/article/details/123738411)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值