vue+elementui builds a backend management interface (5 recursively generates sidebar routing) vue defines a multi-level routing menu

There is a menu tree with submenus under the top menu and submenus under the submenus. . .
At this time, we need to use recursion

1 Define multi-level menu

Modify   the / route of src/router/index.js

  {
    path: '/',
    redirect: '/dashboard',
    name: 'Container',
    component: Container,
    children: [
      {path: 'dashboard', name: '首页', component: Dashboard, 
        children: [
          {path: 'dashboard1', name: '首页1', component: Dashboard,},
          {path: 'dashboard2', name: '首页2', component: Dashboard,
            children: [
              {path: 'dashboard21', name: '首页21', component: Dashboard,},
              {path: 'dashboard22', name: '首页22', component: Dashboard, },
            ] },
        ]
      },
      {path: 'article', name: '文章', component: Article, },
    ]
  }

2 Pull out the Sidebar component

The generated recursive route is placed in the sidebar, so the sidebar component is extracted. The sidebar contains the logo and  recursive route
. Then the SidebarItem is extracted as a separate routing component to facilitate recursive calls.

2.1 Sidebar

Sidebar receives collapse and routing arrays, and introduces the SidebarItem component.

Subcomponent passed in:

  • barIdx: The index of the current route, used to locate the submenu
  • subroute: routing object
  • fatherpath: parent path, such as /, /a/b
<template>
  <div>
    <div class="app-side-logo">
      <img src="@/assets/logo.png"
          :width="collapse ? '60' : '60'"
          height="60" />
    </div>
       
    <el-menu class="el-menu-vertical-demo"
          :default-active="defaultActive"
            router
            :collapse="collapse"
            >
      <SidebarItem v-for="(item, idx) in routes" 
        :subroute="item"
        :fatherpath="fatherPath"
        :barIdx="idx" :key="idx" />
    </el-menu>
  </div>
</template>

<script>
import SidebarItem from './SidebarItem'
export default {
  naem: "Sidebar",
  components: {
    SidebarItem
  },
  props: {
    collapse: {
      type: Boolean
    },
    routes: {
      type: Array
    }
  },
  computed: {
     // 首次进入页面时展开当前页面所属的菜单
    defaultActive(){
      return this.$route.path
    },
    fatherPath(){
      // 这里直接获取路由配置的 '/' 项
      return this.$router.options.routes[1].path
    }
  }
}
</script>

<style>

</style>

2.2 SidebarItem

SidebarItem receives the route, parent route path, parent idx, and then calls itself recursively

<template>
  <!-- 如果当前 subroute 有子节点 -->
  <el-submenu v-if="!subroute.hidden && subroute.children && subroute.children.length > 0"
    :index="genPath(fatherpath, subroute.path)">
    <!-- 创建菜单分组 -->
    <template slot="title">
      <i class="el-icon-menu"></i>
      <span slot="title">{
   
   {subroute.name}}</span>
    </template>

    <!-- 递归调用自身,直到 subroute 不含子节点 -->
    <SidebarItem v-for="(submenu, subidx) in subroute.children"
      :subroute="submenu"
      :fatherpath="genPath(fatherpath, subroute.path)"
      :barIdx="subidx" 
      :key="barIdx + '-' + subidx" 
      />
  </el-submenu>

  <!-- 当前节点不含子节点且非隐藏 -->
  <el-menu-item style="font-weight: 400"
    v-else-if="!subroute.hidden"
    :index="genPath(fatherpath, subroute.path)"
    >{
   
   {subroute.name}}
  </el-menu-item>
  
  <el-menu-item style="font-weight: 400"
    v-else
    :index="genPath(fatherpath, subroute.path)"
    >{
   
   { subroute.name }}
  </el-menu-item>
</template>

<script>
export default {
  name: 'SidebarItem',
  props: {
    subroute: {
      type: Object
    },
    barIdx: {
      type: [String, Number]
    },
    fatherpath: {
      type: String
    }
  },
  computed: {
    // 默认激活的路由, 用来激活菜单选中状态
    defaultActive: function(){
      return this.$route.path
    },
  },
  methods: {
    // 生成侧边栏路由,格式: /a/b/c
    genPath: function(){
      let arr = [ ...arguments ]
      let path = arr.map(v => {
          while (v[0] === '/'){
            v = v.substring(1)
          }
          while(v[-1] === '/'){
            v = v.substring(0, v.length)
          }
        return v 
      }).join('/')
      path = path[0] === '/' ? path : '/'+path
      return path
    },
    handleOpen: function(key, keyPath) {
      console.log(key, keyPath)
    },
    handleClose: function(key, keyPath) {
      console.log(key, keyPath)
    }
  },
  mounted: function(){
    console.log('sidebar routes: ', this.routes)
  }
}
</script>

<style>
</style>

3 Project structure

The directory structure of src at this time

│  App.vue
│  main.js
├─assets
│      logo.png
├─components
│      HelloWorld.vue
│      Sidebar.vue
│      SidebarItem.vue
├─container
│      Container.vue
├─router
│      index.js
├─styles
│      index.scss
└─views
    │  TheLogin.vue
    ├─article
    │      index.vue
    └─dashboard
            index.vue

4 Modify container configuration

src/container/Container.vue  introduces the Sidebar component

<template>
<!-- ... -->
<el-aside class="app-side app-side-left"
          :class="isCollapse ? 'app-side-collapsed' : 'app-side-expanded'">
  <Sidebar :collapse="isCollapse" :routes="$router.options.routes[1].children"/>
</el-aside>
<!-- ... -->
</template>
<script>
import Sidebar from '@/components/Sidebar'
export default {
  name: 'Container',
  components: {
    Sidebar
  },
/** ... */
</script>

5 page effects

The page effect is as follows

Guess you like

Origin blog.csdn.net/u012118993/article/details/107734846