如何拍平多级菜单

两步

关于keep-alive无法缓存多级菜单的解决,之前使用老版本的若依框架,无法做到多级菜单之间切换的一个缓存,这里三步聊聊如何把多级菜单拍平成为一级菜单

一、处理后台数据

1.—vuex —permission.js
在vuex拿到后台路由数据的时候进行拍平。拿到的是一个有children的多级数组,我们遍历成一个单级的数组然后addroutes到路由中。但是显示在侧边栏的依然时多级数组。完成这一步,应该可以通过路径访问到页面了,就像访问静态路由一样。代码如下:

GenerateRoutes({state, commit }) {
      return new Promise(resolve => {
        // 向后端请求路由数据
        getRouters().then(res => {
          const sdata = JSON.parse(JSON.stringify(res.data))
          const rdata = JSON.parse(JSON.stringify(res.data))
          const sidebarRoutes = filterAsyncRouter(sdata)
          const rewriteRoutes = filterAsyncRouter(rdata, true)
          rewriteRoutes.push({ path: '*', redirect: '/404', hidden: true })
          commit('SET_ROUTES', rewriteRoutes)
          commit('SET_SIDEBAR_ROUTERS', sidebarRoutes)   //这里的数据用于展示

          
          let newList=[]
          deepOpen(rewriteRoutes,newList)
          //console.log(rewriteRoutes);
          resolve(newList)  //返回一级路由数组
        })
      })
}



//拍平一级路由的方法
function deepOpen(list,newList){
  list.forEach(item => {
    if(!item.children){
      newList.push(
        {
          path: '/'+item.path,
          component: Layout,
          hidden: true,
          children: [
            {
              path: item.path,
              component: item.component,
              name: item.name,
              meta: item.meta,
            }
          ]
        },
      )
    }else{
      deepOpen(item.children,newList)
    }
  });
}

二、处理路径

—layout —Sidebar --SidebarItem.vue
在布局文件的侧边栏中,修改路径为我们之前设置的路径,要一模一样就ok了,之前设置的是path接上子组件的path所以是两个path /path/path

这里直接上这个组件全部文件代码

 <template>
  <div v-if="!item.hidden">
    <template v-if="hasOneShowingChild(item.children,item) && (!onlyOneChild.children||onlyOneChild.noShowingChildren)&&!item.alwaysShow">
      <app-link v-if="onlyOneChild.meta" :to="resolvePath(item.path)">
        <el-menu-item :index="'/'+item.path+'/'+item.path" :class="{'submenu-title-noDropdown':!isNest}">
          <item :icon="onlyOneChild.meta.icon||(item.meta&&item.meta.icon)" :title="onlyOneChild.meta.title" />
        </el-menu-item>
      </app-link>
    </template>

    <el-submenu v-else ref="subMenu" :index="resolvePath(item.path)" popper-append-to-body>
      <template slot="title">
        <item v-if="item.meta" :icon="item.meta && item.meta.icon" :title="item.meta.title" />
      </template>
      <sidebar-item
        v-for="child in item.children"
        :key="child.path"
        :is-nest="true"
        :item="child"
        :base-path="resolvePath(child.path)"
        class="nest-menu"
      />
    </el-submenu>
  </div>
</template>

<script>
import path from 'path'
import { isExternal } from '@/utils/validate'
import Item from './Item'
import AppLink from './Link'
import FixiOSBug from './FixiOSBug'

export default {
  name: 'SidebarItem',
  components: { Item, AppLink },
  mixins: [FixiOSBug],
  props: {
    // route object
    item: {
      type: Object,
      required: true
    },
    isNest: {
      type: Boolean,
      default: false
    },
    basePath: {
      type: String,
      default: ''
    }
  },
  data() {
    this.onlyOneChild = null
    return {}
  },
  methods: {
    hasOneShowingChild(children = [], parent) {
      const showingChildren = children.filter(item => {
        if (item.hidden) {
          return false
        } else {
          // Temp set(will be used if only has one showing child)
          this.onlyOneChild = item
          return true
        }
      })

      // When there is only one child router, the child router is displayed by default
      if (showingChildren.length === 1) {
        return true
      }

      // Show parent if there are no child router to display
      if (showingChildren.length === 0) {
        this.onlyOneChild = { ... parent, path: '', noShowingChildren: true }
        return true
      }

      return false
    },
    resolvePath(routePath) {
      //console.log(routePath);
      //return routePath
      // if (isExternal(routePath)) {
      //   console.log(1);
      //   return routePath
      // }
      // if (isExternal(this.basePath)) {
      //   console.log(2);
      //   return this.basePath
      // }
      //  return path.resolve(this.basePath, routePath)
      // /console.log(routePath);
      return routePath
    }
  }
}
</script>

重点是resolvePath方法 注意一下传的参数 这里用的是item.path

还有就是applink组件的跳转路径也处理一下,当然我的路径是在这边处理的,你可以直接在上一个组件修改

linkProps(to) {
      if (this.isExternal) {
        return {
          href: '/'+to+'/'+to,
          target: '_blank',
          rel: 'noopener'
        }
      }if(!to){
        return {
        to: '/'
      }
      }
      return {
        to: '/'+to+'/'+to
      }
    },

注意:如果修改完侧边栏的active颜色要点两下才高亮的话,是因为那个default-active的值和el-menu-item的index不一致,改成一样就可以了
这边参考下中间那块代码块的
:index="’/’+item.path+’/’+item.path"

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值