vue-element-admin顶部导航栏的修改

基于vue-element-admin的顶部一级导航栏的调整,因为一级路由过多导致其他元素被挤到第二行,故现在将原来一级路由数组拆分成两个数组,第二个数组以子菜单显示

关键处调整代码

html

html 复制代码
<el-menu
      :active-text-color="variables.menuActiveText"
      :default-active="activeMenu"
      mode="horizontal"
      @select="handleSelect"
    >
      <div v-for="item in displayedRoutes" :key="item.path" class="nav-item">
        <app-link :to="resolvePath(item)">
          <el-menu-item v-if="!item.hidden" :index="item.path">
            <i
              :class="
                item.meta && item.meta.icon ? item.meta.icon : 'el-icon-house'
              "
            ></i>
            {{
              item.meta ? item.meta.title : item.children[0].meta.title
            }}</el-menu-item
          >
        </app-link>
      </div>
      <el-submenu v-if="hiddenRoutes.length > 0" index="coll">
        <template slot="title"><i class="el-icon-more"></i></template>
        <div v-for="item in hiddenRoutes" :key="item.path" class="nav-item">
          <app-link :to="resolvePath(item)">
            <el-menu-item v-if="!item.hidden" :index="item.path">
              <i
                :class="
                  item.meta && item.meta.icon ? item.meta.icon : 'el-icon-house'
                "
              ></i>
              {{
                item.meta ? item.meta.title : item.children[0].meta.title
              }}</el-menu-item
            >
          </app-link>
        </div>
      </el-submenu>
    </el-menu>

js

javascript 复制代码
export default {
  name: "Topbar",
  components: {
    AppLink,
  },
  data() {
    return {
      activeIndex: "1",
      logo: titlePng,
      // avatar: sessionStorage.getItem("avatar"),
      routes: constantRoutes,
    };
  },
  computed: {
    ...mapGetters(["permission_routes", "async_routes", "avatar"]),
    activeMenu() {
      const route = this.$route;
      const { meta, path } = route;
      // if set path, the sidebar will highlight the path you set
      if (meta.activeMenu) {
        return meta.activeMenu;
      }
      // 如果是首页,首页高亮
      if (path === "/dashboard") {
        return "/";
      }
      // 如果不是首页,高亮一级菜单
      const activeMenu = "/" + path.split("/")[1];
      return activeMenu;
    },
    variables() {
      return variables;
    },
    sidebar() {
      return this.$store.state.app.sidebar;
    },
    displayedRoutes() {
      // 这里可以根据需要定义展示的路由项
      return this.routes.slice(0, 9); // 例如,展示前 9 个路由
    },
    hiddenRoutes() {
      // 返回剩余的路由项
      const hidden = this.routes.slice(9); // 省略的路由项
      return hidden.length > 0 ? hidden : []; // 只有在有省略项时返回
    },
  },
  watch: {
    activeMenu(newVal, oldVal) {
      this.handleSelect(newVal);
    },
  },
  mounted() {
    this.initCurrentRoutes();
  },
  methods: {
    // 通过当前路径找到二级菜单对应项,存到store,用来渲染左侧菜单
    initCurrentRoutes() {
      this.$router.addRoutes(this.async_routes);
      this.routes = this.permission_routes; // 动态路由赋值
      const { path } = this.$route;
      let route = this.routes.find(
        (item) => item.path === "/" + path.split("/")[1]
      );
      // 如果找不到这个路由,说明是首页
      if (!route) {
        route = this.routes.find((item) => item.path === "/");
      }
      this.$store.commit("permission/SET_CURRENT_ROUTES", route);
      this.setSidebarHide(route);
    },
    // 判断该路由是否只有一个子项或者没有子项,如果是,则在一级菜单添加跳转路由
    isOnlyOneChild(item) {
      if (item.children && item.children.length === 1) {
        return true;
      }
      return false;
    },
    resolvePath(item) {
      // 如果是个完成的url直接返回
      if (isExternal(item.path)) {
        return item.path;
      }
      // 如果是首页,就返回重定向路由
      if (item.path === "/") {
        const path = item.redirect;
        return path;
      }

      // 如果有子项,默认跳转第一个子项路由
      let path = "";
      /**
       * item 路由子项
       * parent 路由父项
       */
      const getDefaultPath = (item, parent) => {
        // 如果path是个外部链接(不建议),直接返回链接,存在个问题:如果是外部链接点击跳转后当前页内容还是上一个路由内容
        if (isExternal(item.path)) {
          path = item.path;
          return;
        }
        // 第一次需要父项路由拼接,所以只是第一个传parent
        if (parent) {
          path += parent.path + "/" + item.path;
        } else {
          path += "/" + item.path;
        }
        // 如果还有子项,继续递归
        if (item.children) {
          getDefaultPath(item.children[0]);
        }
      };

      if (item.children) {
        getDefaultPath(item.children[0], item);
        return path;
      }

      return item.path;
    },
    handleSelect(key, keyPath) {
      // 把选中路由的子路由保存store
      const route = this.routes.find((item) => item.path === key);
      this.$store.commit("permission/SET_CURRENT_ROUTES", route);
      this.setSidebarHide(route);
    },
    // 设置侧边栏的显示和隐藏
    setSidebarHide(route) {
      if (!route.children || route.children.length === 1) {
        this.$store.dispatch("app/toggleSideBarHide", true);
      } else {
        this.$store.dispatch("app/toggleSideBarHide", false);
      }
    },
    async logout() {
      await this.$store.dispatch("user/logout");
      this.$router.push(`/login?redirect=${this.$route.fullPath}`);
    },
    toggleFullScreen() {
      // 检查浏览器是否支持全屏 API
      if (screenfull.isEnabled) {
        screenfull.toggle(); // 切换全屏模式
      } else {
        console.warn("该浏览器不支持全屏");
      }
    },
  },
};
</script>

拆分逻辑是如果数组长度超过九个就拆分。如果想要根据不同浏览器窗口大小去拆分显示,需要去监听浏览器的实时宽度,计算整行所有元素的长度总和,如果超出则将超出的路由加入子菜单中显示

相关推荐
小旺仔爱代码8 分钟前
AJAX和JSON
前端·ajax·json
清灵xmf15 分钟前
JavaScript 中如何识别异步函数?
开发语言·javascript·async·异步函数
热爱前端的小君同学17 分钟前
实现插入公式的富文本框(tinymce+kityformula-editor)
vue.js
风清扬_jd38 分钟前
Chromium HTML5 新的 Input 类型search对应c++
前端·c++·html5
计算机学姐42 分钟前
基于协同过滤算法的旅游网站推荐系统
vue.js·mysql·算法·mybatis·springboot·旅游·1024程序员节
解道Jdon1 小时前
重新架构:从 Redis 到 SQLite 性能提升
javascript·reactjs
逸狼1 小时前
快速入门HTML
前端·css·html
✎﹏ℳ๓₯㎕1 小时前
el-table实现固定列相同合并切重排序号
javascript·vue.js·elementui
海绵宝宝不喜欢侬1 小时前
vue + elementui 全局Loading效果
前端·vue.js·elementui
会发光的猪。2 小时前
uniapp+华为HBuilder X 4.29跑鸿蒙模拟器报错没有签名授权
javascript·vue.js·华为·uni-app·bug·harmonyos·1024程序员节