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>

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

相关推荐
小曲曲36 分钟前
接口上传视频和oss直传视频到阿里云组件
javascript·阿里云·音视频
学不会•2 小时前
css数据不固定情况下,循环加不同背景颜色
前端·javascript·html
EasyNTS3 小时前
H.264/H.265播放器EasyPlayer.js视频流媒体播放器关于websocket1006的异常断连
javascript·h.265·h.264
活宝小娜4 小时前
vue不刷新浏览器更新页面的方法
前端·javascript·vue.js
程序视点4 小时前
【Vue3新工具】Pinia.js:提升开发效率,更轻量、更高效的状态管理方案!
前端·javascript·vue.js·typescript·vue·ecmascript
coldriversnow4 小时前
在Vue中,vue document.onkeydown 无效
前端·javascript·vue.js
我开心就好o4 小时前
uniapp点左上角返回键, 重复来回跳转的问题 解决方案
前端·javascript·uni-app
开心工作室_kaic5 小时前
ssm161基于web的资源共享平台的共享与开发+jsp(论文+源码)_kaic
java·开发语言·前端
刚刚好ā5 小时前
js作用域超全介绍--全局作用域、局部作用、块级作用域
前端·javascript·vue.js·vue
沉默璇年6 小时前
react中useMemo的使用场景
前端·react.js·前端框架