美文网首页
element菜单嵌套动态渲染

element菜单嵌套动态渲染

作者: 用技术改变世界 | 来源:发表于2021-09-06 16:25 被阅读0次

背景:用element实现一个动态菜单,支持多层级菜单

页面布局:layout文件夹  

 layout.vue(菜单入口) 

side-bar.vue

compomne.vue 右侧视图组件, 支持 路由 iframe切换

1.layout.vue代码

<template>

<template>

  <div class="layout">

    <el-header>海外主题管理台 <span><i v-if="isCollapse"

           class="el-icon-s-unfold"

           @click="isCollapse = false"></i><i class="el-icon-s-fold"

           v-else

           @click="isCollapse = true"></i></span></el-header>

    <el-container>

      <div :class="isCollapse ? 'left-content-colse' : 'left-content'">

        <el-aside style="width:225px">

          <el-scrollbar style="height:100%">

            <el-menu class="el-menu-vertical-demo"

                     :default-active="componentId"

                     @open="handleOpen"

                     @close="handleClose"

                     :collapse-transition="false"

                     :unique-opened="true"

                     :collapse="isCollapse">

              <side-bar :list="menuList"

                        @onActive="onActive"

                        :isCollapse="isCollapse"></side-bar>

            </el-menu>

          </el-scrollbar>

        </el-aside>

      </div>

      <el-main>

        <Components :componentId="componentId"></Components>

      </el-main>

    </el-container>

  </div>

</template>

<script>

import { sideBarData } from './menuConfig'

import SideBar from './side-bar.vue'

import Components from './components.vue'

import { mapGetters } from "vuex";

export default {

  components: { SideBar, Components },

  data() {

    return {

      componentId: '1-1',

      isCollapse: false,

      menuList: sideBarData

    };

  },

  methods: {

    onActive(item) {

      this.componentId = item.id

      this.$store.commit("saveActiveMenuId", this.componentId);

    },

    handleOpen(key, keyPath) {

      console.log(key, keyPath, '1111');

    },

    handleClose(key, keyPath) {

      console.log(key, keyPath);

    },

  },

  watch: {},

  computed: {

    ...mapGetters(["activeMenuId"]),

  },

  created() {

    if (this.activeMenuId) this.componentId = this.activeMenuId;

  },

  mounted() { },

};

</script>

<style lang="less" scoped>

.layout {

  position: absolute;

  top: 0;

  left: 0;

  width: 100vw;

  height: 100%;

  overflow: hidden;

}

.left-content {

  height: 100vh;

  overflow: hidden;

}

.left-content-colse {

  width: 64px;

  height: 100vh;

  background: red;

  overflow: hidden;

}

.el-submenu__title {

  span {

    display: inline-block;

    overflow: hidden;

    text-overflow: ellipsis;

    white-space: nowrap;

  }

}

</style>

<style>

.el-header {

  background-color: #008dff;

  color: #fff;

  font-size: 18px;

  height: auto;

  line-height: 60px;

}

.el-menu {

  background-color: #13254a;

  border-right: none;

  color: #fff;

}

.el-submenu__title {

  color: #fff;

  z-index: 9 !important;

}

.el-menu-item {

  color: #fff;

  border-color: none;

}

.el-aside {

  background-color: #13254a;

  height: 100%;

  color: #fff;

  transition: width 0.5s;

}

.el-submenu__title:hover {

  color: #fff;

  background-color: rgb(0, 141, 255, 0.2) !important;

}

.el-menu-item:hover {

  color: #fff;

  background-color: rgb(0, 141, 255, 0.2) !important;

}

.el-menu-item.is-active {

  color: #fff;

  background-color: #008dff !important;

}

.el-main {

  background-color: #e9eef3;

  color: #333;

}

.el-icon-menu:before {

  content: "\e798";

  color: #fff;

}

/* 

.el-menu-vertical-demo:not(.el-menu--collapse) {

  width: 200px;

  min-height: 400px;

} */

</style>

2.side-bar.vue 代码

<template>

  <fragment>

    <template v-for="(item,index) in list">

      <!-- 标题 -->

      <template v-if="item.children && item.children.length">

        <el-submenu :key="index"

                    :index="item.id"

                    @click="onClick(item)">

          <template :index="item.id"

                    slot="title">

            <i :class="item.icon"

               style="color:#fff"></i>

            <span slot="title">{{item.name}}</span>

          </template>

          <el-menu-item-group>

            <sideBar :list="item.children"

                     v-bind="$attrs"

                     v-on="$listeners"></sideBar>

          </el-menu-item-group>

        </el-submenu>

      </template>

      <!-- 选项 -->

      <template v-else>

        <el-menu-item :key="index"

                      @click="onClick(item)"

                      :index="item.id">

          <i :class="item.icon"></i>

          <!-- <router-link :to="item.path">{{item.name}}</router-link> -->

          <span slot="title">{{item.name}}</span>

        </el-menu-item>

      </template>

    </template>

  </fragment>

</template>

<script>

export default {

  name: "sideBar",

  props: {

    list: Array,

    isCollapse: Boolean

  },

  created() {

  },

  methods: {

    onClick(val) {

      this.$emit('onActive', val)

    }

  }

};

</script>

<style></style>

3.components.vue代码

<template>

  <div class="box"

       v-loading="loading">

    <template>

      <iframe id="myIframe"

              :src="path"

              frameborder="0"></iframe>

    </template>

    <template>

      <router-view></router-view>

    </template>

  </div>

</template>

<script>

import { sideBarData } from './menuConfig'

export default {

  name: "components",

  props: {

    componentId: String,

    list: Array,

  },

  watch: {

    componentId: {

      handler(val) {

        if (val) {

          this.loading = true;

          this.getNode(this.menuList, val);

        }

      },

      immediate: true

    }

  },

  data() {

    return {

      loading: true,

      currentView: 'wallpaper-approve',

      menuList: sideBarData,

      activeNode: {},

      path: '',

    };

  },

  methods: {

    //  递归获取节点

    getNode(dataList, val) {

      if (dataList.length > 0) {

        dataList.forEach(item => {

          if (item.children) {

            this.getNode(item.children, val)

          } else {

            if (item.id === val) {

              this.activeNode = item;

            }

          }

        })

      }

      this.path = this.activeNode.url;

      console.log('this.activeNode', this.activeNode)

    },

    changeviewFun(val) {

      this.currentView = val;

    }

  },

  mounted() {

    let self = this

    var iframe = document.getElementById('myIframe');

    if (!/*@cc_on!@*/0) { //if not IE

      iframe.onload = function () {

        self.loading = false

      };

    } else {

      iframe.onreadystatechange = function () {

        if (iframe.readyState == "complete") {

          self.loading = false

        }

      };

    }

  }

};

</script>

<style>

.box {

  width: 100%;

  height: calc(100% - 60px);

}

.el-main {

  background-color: #f0f2f5 !important;

  color: #f0f2f5;

}

iframe {

  width: 100%;

  height: 100%;

  /* background: red !important; */

}

</style>

4.配置文件

    {

        id:'1',

        name:'一级目录',

        icon: "el-icon-menu",

        type:'',         // 1路由 或  2 iframe

        children: [

            {

                id: '1-1',

                name:'二级目录',

                type:'2',    

                path:'xxx',

                url:  `${BASE_URL}/xxx`

            },

        ]

    },

5. 动态加载菜单收缩字体不显示问题main.js

collapse-transition

// main.js

import Fragment from ‘vue-fragment’

Vue.use(Fragment.Plugin)

参考:Vue-Components-Library/SidebarItem.vue at master · NLRX-WJC/Vue-Components-Library · GitHub

elementui通过router配置多级导航菜单_潇蓝诺依的博客-CSDN博客

相关文章

网友评论

      本文标题:element菜单嵌套动态渲染

      本文链接:https://www.haomeiwen.com/subject/pvhziltx.html