美文网首页
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