vue+element动态路由配置踩过的坑

前言

关于自己使用vue+element写的一个系统中,配置动态路由遇到的问题总结

一、加载不出动态路由

未对接时我把所有的菜单路由都写在了静态路由。当对接时确实能根据不同的用户得到对应的菜单路由。但删除静态路由时,就加载不出页面,排查到的原因是因为处理动态菜单时,没有根据页面的正确url去懒加载vue组件;如:

route['component'] = resolve => require([`@/views/${url}`], resolve)

require加载的必须是对应的vue组件的全路径,这里的url是后端返回的变量,如果后端返回的url只是nameA,而我们的文件位置是views/parentA文件夹下的nameA.vue,就会一直加载不出该页面。
解决方法:
1.后端返回菜单数据的时候,返回一个上一级菜单parentA的名称:

route['component'] = resolve => require([`@/views/parentA/${url}`], resolve)

2.后端返回菜单数据的时候,返回的路径名url就是带有两级结构的菜单。如parentA/url:

route['component'] = resolve => require([`@/views/${url}`], resolve)

3.你也可以不需要parentA文件夹,即把parentA大模块里的小模块全部拆分出来,路径的上一级菜单就同名了。注意区分后端返回数据的大小写。(采取)
在这里插入图片描述

route['component'] = resolve => require([`@/views/${url}/${url}`], resolve)`在这里插入代码片`

二、页面刷新都是跳转到404页面

在设置动态路由的时候,如果在静态路由里面直接写了404页面。会导致刷新页面都是跳到404页面的问题。
在这里插入图片描述
原因:刷新后,都是先加载的静态路由,动态路由是在router.beforeEach路由守卫时判断并添加进去的。所以回先匹配到通配符*,怎么刷新都是404页面
解决:注释掉在静态路由里的404,把404页面push到动态路由后
在这里插入图片描述

三、刷新后对应菜单不高亮

这就涉及到elementUI的NavMenu 导航菜单的问题了, 属性default-active 是当前激活菜单的 index。官网文档举例:
在这里插入图片描述
在这里插入图片描述
可以看出,父组件的default-active和子组件index是一一对应的关系,两个相等才会触发高亮的效果。
注意:每个人对接的时候都要根据后端传回来的数据是什么格式去写代码,总之我们需要保证一点:点击菜单跳转页面的时候,这两个值都需要相等。
父组件:

<template>
  <div class="maincontent">
    <el-menu
      ref="navmenu"
      mode="horizontal"
      background-color="#0e0e35"
      text-color="#5c8e93"
      active-text-color="#9af4eb"
      style="width: 19.2rem; font-size: 0.25rem"
      class="onetitle"
      :class="collapse ? 'menu-bar-collapse-width' : 'menu-bar-width'"
      :collapse="collapse"
      :collapse-transition="false"
      menu-trigger="click"
      :unique-opened="true"
      :default-active="activeIndex"
    >
      <!-- 导航菜单树组件,动态加载菜单 -->
      <NavMenu v-for="item in navTree" :key="item.id" :menu="item"></NavMenu>
    </el-menu>
    <router-view></router-view>
  </div>
</template>
<script>
import { mapState } from "vuex";
import NavMenu from "../../components/NavMenu.vue";
export default {
  name: "MainContent",
  components: {
    NavMenu: NavMenu,
  },
  data() {
    return {
      test: "xx系统",
      // activeIndex: "",
      // 存起来的当前页面的path
      urlPath: "",
    };
  },
  computed: {
    ...mapState({
      appName: (state) => state.app.appName,
      themeColor: (state) => state.app.themeColor,
      collapse: (state) => state.app.collapse,
      navTree: (state) => state.menu.navTree, //菜单树
    }),
    // computed缓存中处理activeIndex=newStr,这个newStr需要和子组件里的index相等
    activeIndex: {
      get: function () {
        // 如果打印出有菜单名
        if (this.urlPath) {
          const str = this.findUrl(this.navTree, this.urlPath) || "";
          console.log("拼接的一级二级菜单id", str);
          let newStr = str.slice(1);
          console.log("newStr", newStr);
          return newStr;
        }
      },
      set: function () {},
    },
  },

  mounted() {
    var firstPath = this.$route.path.toString();
    this.urlPath = firstPath.split("/")[1];
  },
  methods: {
    // 遍历菜单树,拼接id
    findUrl(data, url, str = "") {
      for (let i = 0; i < data.length; i++) {
        let item = data[i];
        if (item.url == url) {
          return str + "-" + item.id;        } else {
          if (item.children.length > 0) {
            let hasStr = this.findUrl(item.children, url, str + "-" + item.id);
            if (hasStr) {
              return hasStr;
            }
          }
        }
      }
    },
  },
};
</script>

子组件:

<template>
  <!-- 二级菜单及以上 -->
  <el-submenu
    v-if="menu.children && menu.children.length >= 1"
    :index="'' + menu.id"
  >
    <template slot="title">
      <i :class="menu.icon"></i>
      <span slot="title" style="font-size: 0.24rem; margin-top: -0.4rem">{{
        menu.menuName
      }}</span>
    </template>
    <NavMenu
      v-for="item in menu.children"
      :key="item.id"
      :menu="item"
    ></NavMenu>
    <!-- <el-menu-item v-for="item in menu.children"
      :key="item.id"
      :menu="item"
      @click="handleRoute(menu)">
    <i :class="menu.icon"></i>
    <span slot="title" style="font-size: 0.24rem">{{ menu.menuName }}</span>
  </el-menu-item> -->
  </el-submenu>
  <!-- 一级菜单 -->
  <el-menu-item v-else :index="'' + menu.parentId + '-' + '' + menu.id" @click="handleRoute(menu)">
    <i :class="menu.icon"></i>
    <span slot="title" style="font-size: 0.24rem">{{ menu.menuName }}</span>
  </el-menu-item>
</template>

<script>
import { getIFrameUrl, getIFramePath } from "@/utils/iframe";
export default {
  name: "NavMenu",
  // 父组件传过来的
  props: {
    menu: {
      type: Object,
      required: true,
    },
  },
  watch: {
    menu: {
      deep: true, //true为进行深度监听,false为不进行深度监听
      handler(newVal) {
        // console.log("改变", newVal);
      },
    },
  },
  methods: {
    handleRoute(menu) {
      //这里打印的active就是子组件的index,要与父组件的activeIndex相等
      console.log('子组件打印了active','' + menu.parentId + '-' + '' + menu.id)
      // 如果是嵌套页面,转换成iframe的path
      let path = getIFramePath(menu.url);
      if (!path) {
        path = menu.url;
        // console.log(path)
      }
      // 通过菜单URL跳转至指定路由
      this.$router.push("/" + path);
    },
  },
};
</script>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值