This is the fifth day of my participation in Gwen Challenge

preface

Recently, I encountered a design when DOING background system, that is, the top is the first level of the menu, and the sidebar is the second level of the menu or more. But after I baidu a circle found this kind of design more mature or ready-made almost no. It feels strange that something that should be a common design is not readily available. So I implemented one myself. Let’s talk about it again today, and make a simple basic function, which looks like this:

The drawing is a little ugly, after all, it’s not professional

Click menu 1 at the top to see the menu below. Click Menu 2 to replace the side menu with the sub-menu below menu 2.

Analysis of the

In fact, the layout is very simple. It is divided into three parts: the top, the sidebar, and the content area. Here is just a simple function to achieve the interface beautification will not be repeated here.

implementation

New project

This is implemented using Vue, element-UI, so new projects are skipped, just like other Vue projects.

Top component implementation

Implement the top menu component by creating a header component in the project Components directory. There’s nothing at the top, just a menu, directly using elementUI’s menu component. The key codes are as follows:

<el-menu mode="horizontal" @select="handleSelect" :default-active="activeRoute()"> <el-menu-item class="list-item" :index="item.url" v-for="item in items" :key="item.url"> <i :class="item.icon"></i> <span slot="title">{{ item.name }}</span> </el-menu-item> </el-menu> export default { data() { return { items: []}}, Created () {this.getUserInfo() // Sets the default sidebar menu handling this.defaultMenu('/'+this.$route.path.split('/')[1])}, methods: {// Bind to the corresponding level 1 menu according to the path, ActiveRoute () {return '/'+this.$route.path.split('/')[1]} Var datas = [{name:' menu-1', url:'/menu-1', children:[{name:' menu-1-1 ', Url: '/'/child menu - 1-1, children: [{name: 'menu in the 1-1-1 s, url:' / / sub/child menu - 1-1-1 '}, {name: 'menu in the 1-1-2 s', Url: '/ / sub/child menu - 1-1-2'}}, {name: 1-2 ' 'menu, url:'/child/menu - 1-2 ', children: [{name: 'menu in the 1-2-1 s', Url: '/ / child menu - 1-2 / sub - 1'},]]}}, {name: '2' menu, url: '/ menu - 2' children: [{name: 'menu 2-1, url:'/menu - 2 / child - 1 ', Children: [{name: 'menu in the 2-1-1 s, url:'/menu/sub - 1-2 / child - 1 '}]}, {name: 'menu 2-2, url:'/menu - 2 / child - 2 '}}, {name: '3' menu, url: '/ menu - 3' children: [{name: 'menu 3-1, url:'/menu - 3 / child - 1 ', children: [{name: 'menu in the 3-1-1 s', url:'/menu-3/child-1/sub-1' } ] } ] } ] this.items = datas }, handleSelect(index){ this.defaultMenu(index) this.$router.push(index) }, defaultMenu(index){ let route = this.items.find(item=>item.url === index) this.$store.commit("changeValue", { name: "menus", value: route }) } } }Copy the code

So we’re done with the top menu. There is no icon in the menu above, I will not use icon here, you can add ICONS by yourself.

Sidebar menu component implementation

The sidebar menu for now is just the structure, the real data needs to be processed later. The key codes are as follows:

<div class="sidebar">
    <el-scrollbar class="scroll-wrapper">
        <el-menu class="sidebar-el-menu" :default-active="$route.path" unique-opened router>
            <subItem :items="items" />
        </el-menu>
    </el-scrollbar>
</div>

import subItem from "./subitem"
export default {
    props:['items'],
    components: {
        subItem
    }
}
Copy the code

Here is the code for the subItem component of a multilevel menu using regular recursion:

<template>
	<div>
		<template v-for="item in items">
			<el-submenu :index="item.url" v-if="item.children && item.children.length > 0" :key="item.url">
				<template slot="title">
					<span>{{ item.name }}</span>
				</template>
				<subitem :items="item.children" />
			</el-submenu>
			<el-menu-item :index="item.url" v-else :key="item.url">
				<span slot="title">{{ item.name }}</span>
			</el-menu-item>
		</template>
	</div>
</template>

<script>
export default {
	name:"subitem",
	props:{
		items:Array
	}
}
</script>
Copy the code

That completes the sidebar menu, where the array of menus needs to be passed in.

Define the routing

Now we need to define the route, according to the design, there are three levels, so we need to design a three-level route, the routing code is as follows:

{ path: '/', component: () => import('.. /layouts/ frameframe.vue '), meta: {title: 'readme'}, children: [{path: "/menu-1", Component: () => import("@/layouts/children.vue"), meta: {title: "menu 1"}, redirect: "/menu-1/child-1/sub-1", children: [{path: "Child-1 ", Component: () => import("@/layouts/page.vue"), meta: {title:" menu 1-1"}, children: [{path: "Sub - 1", component: () = > import (" @ / views/menu111. Vue "), meta: {title: "the 1-1-1 menu"}}, {path: "sub - 2", the component: () = > import (" @ / views/menu112. Vue "), meta: {title: "the 1-1-2 menu"}}}]]}, {path: "/ menu - 2", component: () => import("@/layouts/children.vue"), meta: {title: "menu 2"}, redirect: "/menu-2/child-1/sub-1", children: [{path: "Child-1 ", Component: () => import("@/layouts/page.vue"), meta: {title:" menu 2-1"}, children: [{path: "Sub - 1", component: () = > import (" @ / views/menu211. Vue "), meta: {title: "the 2-1-1 menu"}}}, {path: "Child-2 ", Component: () => import("@/layouts/page.vue"), meta: {title:" menu 2-2"}, children: [{path: "Sub - 1", component: () = > import (" @ / views/menu221. Vue "), meta: {title: "the 2-2-1 menu"}}}}]] and {path: "/menu-3", Component: () => import("@/layouts/children.vue"), meta: {title: "menu 3"}, redirect: "/menu-3/child-1/sub-1", children: [ { path: "child-1", component: () => import("@/layouts/page.vue"), meta: { title: "Menu 3-1"}, children: [{path: "sub-1", Component: () => import("@/views/menu311.vue"), meta: {title: "Menu 3-1-1"}}]}]}]}Copy the code

The route is also defined, the next is to implement several layout data components in the route.

Layout component implementation

The first is framework components

This is the outermost component, which is the layout component that only contains the top menu. The code is as follows:

<template> <el-container class="main"> <myHeader /> <router-view /> </el-container> </template> <script> import myHeader  from '@/components/header/index.vue' export default { components: { myHeader } } </script>Copy the code

Sidebar menu layout components

Next is the menu layout component of the sidebar, which contains the menu component in the current, the key data transfer is here. The code is as follows:

<template>
  <el-container>
    <mySidebar :items="items" />
    <el-container>
      <router-view />
    </el-container>
  </el-container>
</template>

<script>
import mySidebar from '@/components/sidebar/index.vue'
export default {
  components: {
    mySidebar
  },
  data() {
    return {
      items:[]
    }
  },
  watch:{
    $route(){
      this.items = this.$store.state.menus.children
    }
  },
  created() {
    this.items = this.$store.state.menus.children
  }
}
</script>
Copy the code

The final level is the layout component of the specific page

This level of the component is not mentioned, it is a router-view, you can modify other needs. Finally, string all the code together, write some style and you can see the effect.

The effect

Merge the component and code to see the effect, which looks like this:

conclusion

Actually is a very simple function, a little attention is good, we can expand and enrich according to their own needs on the line.