Vue 与 elementui 实现递归组件菜单

发布于 2021-11-28 21:12:55 字数 7283 浏览 1147 评论 0

主要讲如何使用 vue 实现一个递归组件,一般这种组件,多用于项目中的导航菜单。递归的主要思想就是自己调用自己,然后有结束条件。递归组件也是一样,在组建内使用自己(需要注意的是一个 name 属性,这个属性相当于组件的标识,自己调用自己就用的这个,其实 keep-alive 用到的 exclude 等也是这个属性而不是路由里面的 name。),下面是我写的一个递归的导航菜单,毕竟看代码实例来的更清晰点。

主菜单

<template>
  <div class="lj-left-menu">
    <el-menu
      :default-active="activeIndex"
      class="el-menu-vertical-demo"
      background-color="#242F4B"
      text-color="#D2D5DE"
      active-text-color="#468FFE"
      ref="activeIndex"
    >
      <menu-item :menuData="menuData"></menu-item>
    </el-menu>
  </div>
</template>

<script>
import menuItem from "./menuItem";
export default {
  name: "leftMenu",

  components: {
    menuItem,
  },

  data() {
    return {
      activeIndex: null, // 当前展开菜单
      menuData: [
        {
          id: "0",
          title: "首页",
          router: "/home",
          icon: "el-icon-s-home",
          children: [],
        },
        {
          id: "1",
          title: "巡检",
          icon: "el-icon-place",
          router: "/home",
          children: [
            {
              id: "1-0",
              title: "智能巡检设置",
              icon: "",
              router: "/home",
              children: [],
            },
            {
              id: "1-1",
              title: "巡检记录",
              icon: "",
              router: "/home",
              children: [],
            },
            {
              id: "1-2",
              title: "人工巡检任务",
              icon: "",
              router: "/home",
              children: [],
            },
            {
              id: "1-3",
              title: "故障维修",
              icon: "",
              router: "/home",
              children: [],
            },
            {
              id: "1-4",
              title: "保养维护任务",
              icon: "",
              router: "/home",
              children: [],
            },
          ],
        },
        {
          id: "2",
          title: "设备管理",
          icon: "el-icon-s-management",
          router: "",
          children: [
            {
              id: "2-0",
              title: "设备管理",
              icon: "",
              router: "/home",
              children: [],
            },
            {
              id: "2-1",
              title: "设备生命周期管理",
              icon: "",
              router: "/home",
              children: [],
            },
          ],
        },
        {
          id: "3",
          title: "告警管理",
          icon: "el-icon-sunrise",
          router: "/home",
          children: [
            {
              id: "3-0",
              title: "巡检告警",
              icon: "",
              router: "/home",
              children: [],
            },
          ],
        },
        {
          id: "4",
          title: "消息中心",
          icon: "el-icon-chat-dot-square",
          router: "/home",
          children: [
            {
              id: "4-0",
              title: "消息列表",
              icon: "",
              router: "/home",
              children: [],
            },
          ],
        },
        {
          id: "5",
          title: "系统管理",
          icon: "el-icon-setting",
          router: "/home",
          children: [
            {
              id: "5-0",
              title: "用户管理",
              icon: "",
              router: "/home",
              children: [
                {
                  id: "5-0-1",
                  title: "权限管理",
                  icon: "",
                  router: "/home",
                  children: [],
                },
              ],
            },
            {
              id: "5-1",
              title: "角色管理",
              icon: "",
              router: "/home",
              children: [],
            },
            {
              id: "5-2",
              title: "权限管理",
              icon: "",
              router: "/home",
              children: [],
            },
          ],
        },
      ],
    };
  },
  computed: {},
  mounted() {},
  methods: {},
  watch: {
    $route: { // 监听路由,确保刷新后当前页面与导航状态一致。
      handler(val) {
        this.activeIndex = val.meta.id;
      },
      deep: true,
      immediate: true,
    },
  },
};
</script>

<style lang='scss' scoped>
.lj-left-menu {
  width: 100%;
  height: 100%;
  overflow: auto;
}
</style>

递归组件

<template>
  <div class="lj-menu-item">
    <template v-for="item in menuData">
      <template v-if="item.children.length">
        <el-submenu :index="item.id" :key="item.id">
          <template slot="title">
            <template v-if="item.icon">
              <i :class="item.icon"></i>
              <span></span>
            </template>
            <template v-else>
              <div class="radius"></div>
              <div></div>
            </template>
          </template>
          <menu-item :menuData="item.children"></menu-item>
        </el-submenu>
      </template>
      <template v-else>
        <el-menu-item
          :index="item.id"
          :key="item.id"
          @click="goRouter(item.router)"
        >
          <template v-if="item.icon">
            <i :class="item.icon"></i>
            <span></span>
          </template>
          <template v-else>
            <div class="radius"></div>
            <div></div>
          </template>
        </el-menu-item>
      </template>
    </template>
  </div>
</template>

<script>
export default {
  name: "menuItem",

  data() {
    return {
      nowRouter: null,
    };
  },

  props: {
    menuData: {
      type: Array,
      default: () => {},
    },
  },

  computed: {},

  mounted() {
    this.nowRouter = this.$route.path;
  },

  methods: {
    // 路由跳转
    goRouter(data) {
      if (this.nowRouter === data) {
        return;
      } else {
        this.nowRouter = data;
        this.$router.push(data);
      }
    },
  },
};
</script>

<style lang="scss">
.el-menu-item.is-active {
  background: linear-gradient(90deg, #2b579c 0%, rgba(52, 89, 150, 0) 100%);
  border-left: 2px solid #0086ff;
}
.el-menu-item:focus,
.el-menu-item:hover {
  background: linear-gradient(90deg, #2b579c 0%, rgba(52, 89, 150, 0) 100%);
  border-left: 2px solid #0086ff;
}
.el-submenu__title {
  i {
    color: #00d7ff !important;
  }
}
.el-menu-item,
.el-submenu__title {
  display: flex;
  justify-content: flex-start;
  align-items: center;
  .radius {
    width: 8px;
    height: 8px;
    background: #468ffe;
    opacity: 0.6;
    border-radius: 50%;
    margin-right: 10px;
  }
  i {
    color: #00d7ff !important;
  }
}
</style>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

JSmiles

生命进入颠沛而奔忙的本质状态,并将以不断告别和相遇的陈旧方式继续下去。

0 文章
0 评论
84961 人气
更多

推荐作者

醉城メ夜风

文章 0 评论 0

远昼

文章 0 评论 0

平生欢

文章 0 评论 0

微凉

文章 0 评论 0

Honwey

文章 0 评论 0

qq_ikhFfg

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文