Vue iview-admin框架二級菜單改成三級菜單

最近在用 iview-admin的Vue後臺模板,從git上下載後發現左側導航欄最多支持到二級菜單,也發現不少童鞋在問如何實現三級菜單。在實際的應用場景中仍是會出現三級菜單的需求的,木有其餘好辦法,只能本身手動改代碼了。vue

1. 第一步:首先改寫VUE中的模板,修改sidebarMenu.vue文件,文件具體目錄建下圖:ios

clipboard.png

將Menu導航菜單組件的的二級嵌套結構改成三級嵌套,無非就是判斷二級路由頁面下是否有children屬性及是否含有子元素,有的話直接v-for循環生成子元素標籤,新結構以下:git

<template>
    <Menu ref="sideMenu" :active-name="$route.name" :open-names="openNames" :theme="menuTheme" width="auto" @on-select="changeMenu">
        <template v-for="item in menuList">
            <MenuItem v-if="item.children.length<=1" :name="item.children[0].name" :key="'menuitem' + item.name">
                <Icon :type="item.children[0].icon || item.icon" :size="iconSize" :key="'menuicon' + item.name"></Icon>
                <span class="layout-text" :key="'title' + item.name">{{ itemTitle(item.children[0]) }}</span>
            </MenuItem>

            <Submenu v-if="item.children.length > 1" :name="item.name" :key="item.name">
                <template slot="title">
                    <Icon :type="item.icon" :size="iconSize"></Icon>
                    <span class="layout-text">{{ itemTitle(item) }}</span>
                </template>
                <template v-for="child in item.children">
                    <!-- 添加條件判斷是否還有三級菜單 v-if="child.children.length<=1"  -->
                    <MenuItem   v-if="isThirdLeveMenu(child)==false"  :name="child.name" :key="'menuitem' + child.name">
                        <Icon :type="child.icon" :size="iconSize" :key="'icon' + child.name"></Icon>
                        <span class="layout-text" :key="'title' + child.name">{{ itemTitle(child) }}</span>
                    </MenuItem>
                    <!-- 如下爲新增 添加條件判斷若是有三級菜單 則增長三級菜單 -->
                    <Submenu v-if="isThirdLeveMenu(child)==true" :name="child.name" :key="'menuitem' + child.name">
                         <template slot="title">
                             <Icon :type="child.icon" :size="iconSize" :key="'icon' + child.name"></Icon>
                              <span class="layout-text" :key="'title' + child.name">{{ itemTitle(child) }}</span>
                         </template>
                         <template v-for="son in child.children">
                              <MenuItem :name="son.name" :key="'menuitem' + son.name">
                                   <Icon :type="son.icon" :size="iconSize" :key="'icon' + son.name"></Icon>
                                   <span class="layout-text" :key="'title' + son.name">{{ itemTitle(son) }}</span>
                              </MenuItem>
                         </template>
                    </Submenu>
                    <!-- 以上爲新增 -->
                </template>
            </Submenu>
        </template>
    </Menu>
</template>

組件中methods下添加一個方法isThirdLeveMenu,判斷是否含有children屬性:數組

methods: {
    changeMenu(active) {
      this.$emit("on-change", active);
    },
    itemTitle(item) {
      if (typeof item.title === "object") {
        return this.$t(item.title.i18n);
      } else {
        return item.title;
      }
    },
    isThirdLeveMenu(child){
       if(child.children){
           if(child.children.length>0)return true;
           else  return false;
       }
       else {
         return false;
       }
    }
  },

第二步:修改建立當前path路徑的邏輯方法:setCurrentPath ,在libs文件夾下util.js文件中:app

util.setCurrentPath = function (vm, name) {
    let title = '';
    let isOtherRouter = false;
    vm.$store.state.app.routers.forEach(item => {
        if (item.children.length === 1) {
            if (item.children[0].name === name) {
                title = util.handleTitle(vm, item);
                if (item.name === 'otherRouter') {
                    isOtherRouter = true;
                }
            }
        } else {
            item.children.forEach(child => {
                if (child.name === name) {
                    title = util.handleTitle(vm, child);
                    if (item.name === 'otherRouter') {
                        isOtherRouter = true;
                    }
                }
            });
        }
    });
    let currentPathArr = [];
    //去首頁
    if (name === 'home_index') {
        currentPathArr = [
            {
                title: util.handleTitle(vm, util.getRouterObjByName(vm.$store.state.app.routers, 'home_index')),
                path: '',
                name: 'home_index'
            }
        ];
    } 
    //去導航菜單一級頁面或者OtherRouter路由中的頁面
    else if ((name.indexOf('_index') >= 0 || isOtherRouter) && name !== 'home_index') {
        currentPathArr = [
            {
                title: util.handleTitle(vm, util.getRouterObjByName(vm.$store.state.app.routers, 'home_index')),
                path: '/home',
                name: 'home_index'
            },
            {
                title: title,
                path: '',
                name: name
            }
        ];
    } 
    //去導航菜單二級頁面或三級頁面
    else {
        let currentPathObj = vm.$store.state.app.routers.filter(item => {

            var hasMenu;
            if (item.children.length <= 1) {
                hasMenu = item.children[0].name === name;
                return hasMenu;
            } else {
                let i = 0;
                let childArr = item.children;
                let len = childArr.length;
                while (i < len) {
                    //若是是三級頁面按鈕,則在二級按鈕數組中找不到這個按鈕名稱
                    //須要二級頁面下可能出現三級子菜單的狀況邏輯加入
                    if (childArr[i].name === name) {
                        hasMenu = true;
                        return hasMenu;
                    }
                    i++;
                }
                //若是一級,二級菜單下都沒有此按鈕名稱,則遍歷三級菜單
                if(!hasMenu){
                    for(let m=0;m<childArr.length;m++){
                        if(!childArr[m].children) continue;
                        let sonArr = childArr[m].children;
                        for(let n=0;n<sonArr.length;n++){
                            if(sonArr[n].name === name){
                                hasMenu = true;
                                return hasMenu;
                            }
                        }
                    }
                }
                return false;
            }
        })[0];
       
        if (currentPathObj.children.length <= 1 && currentPathObj.name === 'home') {
            currentPathArr = [
                {
                    title: '首頁',
                    path: '',
                    name: 'home_index'
                }
            ];
        } else if (currentPathObj.children.length <= 1 && currentPathObj.name !== 'home') {
            currentPathArr = [
                {
                    title: '首頁',
                    path: '/home',
                    name: 'home_index'
                },
                {
                    title: currentPathObj.title,
                    path: '',
                    name: name
                }
            ];
        } else {
             //若是是三級頁面按鈕,則在二級按鈕數組中找不到這個按鈕名稱
             //須要二級頁面下可能出現三級子菜單的狀況邏輯加入
            let childObj = currentPathObj.children.filter((child) => {
                return  child.name === name;
            })[0];

           // let thirdLevelObj =
           console.log(childObj)
           //二級頁面
            if (childObj) {
                currentPathArr = [
                    {
                        title: '首頁',
                        path: '/home',
                        name: 'home_index'
                    },
                    {
                        title: currentPathObj.title,
                        path: '',
                        name: currentPathObj.name
                    },
                    {
                        title: childObj.title,
                        path: currentPathObj.path + '/' + childObj.path,
                        name: name
                    }
                ];
            }
            //childobj爲undefined,再從三級頁面中遍歷
            else {
                let thirdObj;
                let childObj = currentPathObj.children.filter((child) => {
                    let hasChildren;
                    hasChildren = child.name === name;
                    if (hasChildren) return hasChildren

                    if (child.children) {
                        let sonArr = child.children;
                        for (let n = 0; n < sonArr.length; n++) {
                            if (sonArr[n].name === name) {
                                thirdObj = sonArr[n];
                                hasChildren = true;
                                return hasChildren;
                            }
                        }
                    }
                    return hasChildren
                })[0];

                if(thirdObj && childObj){
                    currentPathArr = [
                        {
                            title: '首頁',
                            path: '/home',
                            name: 'home_index'
                        },
                        {
                            title: currentPathObj.title,
                            path: '',
                            name: currentPathObj.name
                        },
                        {
                            title: childObj.title,
                            path: '',               //設爲空是由於此二級菜單沒有實際頁面且用於麪包屑組件顯示,path爲空的將不可單擊
                            name: childObj.name
                        },
                        {
                            title: thirdObj.title,
                            path: currentPathObj.path + '/' + childObj.path + '/' + thirdObj.path,
                            name: thirdObj.name
                        }
                    ];
                }
                
            }
            
        }
    }
    
    vm.$store.commit('setCurrentPath', currentPathArr);
    return currentPathArr;
};

第三步:創建三級頁面test-child.vue,testcaca.vue和三級路由的容器組件artical-publish-center.vue
artical-publish-center.vue結構以下圖: 要有<rout-view>標籤iview

clipboard.png

其餘兩個三級頁面vue隨便寫了:ide

clipboard.png

第四步:到這裏,容器能夠實現期待已久三級菜單了,^_^. 在router裏添加三級頁面路由,router文件夾下router.js中:
加到appRouter中吧,能夠放到title: '組件'的children數組中:ui

{
                path: 'artical-publish',
                title: '用戶配置',
                name: 'artical-publish',
                icon: 'compose',
                component: () => import('@/views/test/artical-publish-center.vue'), //引用三級頁面的中間容器層
                children:[
                    {
                        path: 'testcaca',
                        icon: 'ios-pause',
                        name: 'testcaca',
                        title: 'test4',
                        component: () => import('@/views/test/testcaca.vue')
                    },
                    {
                        path: 'test-child',
                        icon: 'ios-pause',
                        name: 'test-child',
                        title: 'test-child',
                        component: () => import('@/views/test/test-child.vue')
                    }
                ]
            }

最後保存,運行你的項目,看下三級菜單出來了吧:this

clipboard.png

相關文章
相關標籤/搜索