视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
Vue iview-admin框架二级菜单改为三级菜单的方法
2020-11-27 22:12:04 责编:小采
文档

最近在用 iview-admin的Vue后台模板,从git上下载后发现左侧导航栏最多支持到二级菜单,也发现很多童鞋在问如何实现三级菜单。在实际的应用场景中还是会出现三级菜单的需求的,木有其他好办法,只能自己手动改代码了。

1. 第一步:首先改写VUE中的模板,修改sidebarMenu.vue文件,文件具体目录建下图:

将Menu导航菜单组件的的二级嵌套结构改为三级嵌套,无非就是判断二级路由页面下是否有children属性及是否含有子元素,有的话直接v-for循环生成子元素标签,新结构如下:

<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文件中:

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>标签

其他两个三级页面vue随便写了:

第四步:到这里,容器可以实现期待已久三级菜单了,^_^. 在router里添加三级页面路由,router文件夹下router.js中:
加到appRouter中吧,可以放到title: '组件'的children数组中:

{
 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')
 }
 ]
 } 

最后保存,运行你的项目,看下三级菜单出来了吧:

下载本文
显示全文
专题