1.封装简单的Menu组件
代码目录结构如下:
router.js:
import Home from "@/views/Home.vue"; export default [ { path: "/", alias: "/home_page", name: "home", //加上name属性 命名路由 component: Home, props: route => ({ food: route.query.food }), beforeEnter: (to, from, next) => { // if (from.name === "about") alert("这是从about来的"); // else alert("这不是从about来的"); next(); } }, { path: '/menu_page', name: 'menu_page', component: () => import('@/views/menu-page.vue') }, { path: "*", component: () => import("@/views/error_404.vue") } ];
menu-page.vue:
<template> <div class="menu-box"> <a-menu> <a-menu-item>1111</a-menu-item> <a-menu-item>2222</a-menu-item> <a-submenu> <div slot="title">3333</div> <a-menu-item>3333-11</a-menu-item> <a-submenu> <div slot="title">3333-22</div> <a-menu-item>3333-22-11</a-menu-item> <a-menu-item>3333-22-22</a-menu-item> </a-submenu> </a-submenu> </a-menu> </div> </template> <script> import menuComponents from "_c/menu"; const { AMenu, AMenuItem, ASubmenu } = menuComponents; export default { name: "menu_page", components: { AMenu, AMenuItem, ASubmenu } }; </script> <style lang="less"> .menu-box { 300px; height: 400px; } </style>
a-menu.vue:
<template> <div class="a-menu"> <slot></slot> </div> </template> <script> export default { name: "AMenu" }; </script> <style lang="less"> .a-menu { & * { list-style: none; } ul { padding: 0; margin: 0; } } </style>
a-menu-item.vue:
<template> <li class="a-menu-item"> <slot></slot> </li> </template> <script> export default { name: "AMenuItem" }; </script> <style lang="less"> .a-menu-item { background: rgb(90, 92, 104); color: #fff; } </style>
a-submenu.vue:
<template> <ul class="a-submenu"> <div class="a-submenu-title" @click="handlerClick"> <slot name="title"></slot> <span class="shrink-icon" :style="{transform:`rotateZ(${showChild ? 0 : 180}deg)`}">^</span> </div> <div v-show="showChild" class="a-submenu-child-box"> <slot></slot> </div> </ul> </template> <script> export default { name: "ASubmenu", data() { return { showChild: false }; }, methods: { handlerClick() { this.showChild = !this.showChild; } } }; </script> <style lang="less"> .a-submenu{ background: rgb(33, 35, 39); &-title{ color: #fff; position: relative; .shrink-icon{ position:absolute; top:0; right: 10px; } } &-child-box{ overflow: hidden; padding-left: 20px; } li{ background: rgb(33, 35, 39); } } </style>
运行效果:
2.递归组件
在以上提到的简单Menu的基础上,继续封装一个Recursivemenu(递归组件):
ReSubmenu.vue:
<template> <a-submenu> <div slot="title">{{ parent.title }}</div> <template v-for="(item, i) in parent.children"> <a-menu-item v-if="!item.children" :key="`menu_item_${index}_${i}`">{{ item.title }}</a-menu-item> <re-submenu v-else :key="`menu_item_${index}_${i}`" :parent="item"></re-submenu> </template> </a-submenu> </template> <script> import menuComponents from '_c/menu' const { AMenuItem, ASubmenu } = menuComponents export default { name: 'ReSubmenu', components: { AMenuItem, ASubmenu }, props: { parent: { type: Object, default: () => ({}) }, index: Number } } </script>
index.js:
import ReSubmenu from "./ReSubmenu.vue"; export default ReSubmenu;
menu-page.vue:
<template> <div class="menu-box"> <a-menu> <template v-for="(item, index) in list"> <a-menu-item v-if="!item.children" :key="`menu_item_${index}`">{{ item.title }}</a-menu-item> <re-submenu v-else :key="`menu_item_${index}`" :parent="item" :index="index"></re-submenu> </template> </a-menu> </div> </template> <script> import menuComponents from "_c/menu"; import ReSubmenu from "_c/Recursivemenu"; const { AMenu, AMenuItem, ASubmenu } = menuComponents; export default { name: "menu_page", components: { AMenu, AMenuItem, ASubmenu, ReSubmenu }, data() { return { list: [ { title: "1111" }, { title: "2222" }, { title: "3333", children: [ { title: "3333-1" }, { title: "3333-2", children: [ { title: "3333-2-1" }, { title: "3333-2-2" }, { title: "3333-2-3", children: [ { title: "3333-2-3-1" }, { title: "3333-2-3-2" } ] } ] } ] }, { title: "4444" } ] }; } }; </script> <style lang="less"> .menu-box { 300px; height: 400px; } </style>
运行效果: