Vue 开发实战实战篇 # 31:如何将菜单和路由结合
Posted 凯小默
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Vue 开发实战实战篇 # 31:如何将菜单和路由结合相关的知识,希望对你有一定的参考价值。
说明
【Vue 开发实战】学习笔记。
实现效果
BasicLayout.vue
<template>
<div :class="[`nav-theme-$navTheme`, `nav-layout-$navLayout`]">
<a-layout id="components-layout-demo-side" style="min-height: 100vh">
<a-layout-sider
v-if="navLayout === 'left'"
v-model="collapsed"
width="256px"
collapsible
:theme="navTheme"
:trigger="null"
>
<div class="logo">Ant Design Vue Pro</div>
<SiderMenu :theme="navTheme"/>
</a-layout-sider>
<a-layout>
<a-layout-header style="background: #fff; padding: 0">
<a-icon
class="trigger"
:type="collapsed ? 'menu-unfold' : 'menu-fold'"
@click="collapsed = !collapsed"
></a-icon>
<Header />
</a-layout-header>
<a-layout-content style="margin: 0 16px">
<router-view></router-view>
</a-layout-content>
<a-layout-footer style="text-align: center">
<Footer />
</a-layout-footer>
</a-layout>
</a-layout>
<SettingDrawer />
</div>
</template>
<script>
import Header from "./Header";
import SiderMenu from "./SiderMenu";
import Footer from "./Footer";
import SettingDrawer from "../components/SettingDrawer";
export default
data()
return
collapsed: false,
;
,
components:
Header,
SiderMenu,
Footer,
SettingDrawer,
,
computed:
navTheme()
return this.$route.query.navTheme || "dark";
,
navLayout()
return this.$route.query.navLayout || "left";
,
,
;
</script>
<style lang="less" scoped>
.trigger
padding: 0 20px;
line-height: 64px;
font-size: 20px;
&:hover
background-color: #eeeeee;
.logo
height: 64px;
line-height: 64px;
text-align: center;
overflow: hidden;
.nav-theme-dark
.logo
color: #fff;
</style>
SiderMenu.vue
<template>
<div style="width: 256px">
<a-menu
:selectedKeys="selectedKeys"
:openKeys.sync="openKeys"
mode="inline"
:theme="theme"
>
<template v-for="item in menuData">
<a-menu-item v-if="!item.children"
:key="item.path"
@click="() => $router.push(path: item.path, query: $router.query)"
>
<a-icon v-if="item.meta.icon" :type="item.meta.icon" />
<span> item.meta.title </span>
</a-menu-item>
<sub-menu v-else :key="item.path" :menu-info="item" />
</template>
</a-menu>
</div>
</template>
<script>
import SubMenu from "./SubMenu.vue";
export default
props:
theme:
type: String,
default: "dark"
,
components:
"sub-menu": SubMenu
,
data()
this.selectedKeysMap = ;
this.openKeysMap = ;
const menuData = this.getMenuData(this.$router.options.routes)
return
collapsed: false,
menuData,
selectedKeys: this.selectedKeysMap[this.$route.path],
openKeys: this.collapsed ? [] : this.openKeysMap[this.$route.path]
;
,
watch:
"$route.path": function(val)
this.selectedKeys = this.selectedKeysMap[val];
this.openKeys = this.collapsed ? [] : this.openKeysMap[val];
,
methods:
getMenuData(routes = [], parentKeys = [], selectedKeys)
const menuData = [];
routes.forEach(item =>
if(item.name && !item.hideInMenu)
this.openKeysMap[item.path] = parentKeys;
this.selectedKeysMap[item.path] = [selectedKeys || item.path];
const newItem = ...item;
delete newItem.children;
if(item.children && !item.hideChildrenInMenu)
newItem.children = this.getMenuData(item.children, [...parentKeys, item.path]);
else
this.getMenuData(
item.children,
selectedKeys ? parentKeys : [...parentKeys, item.path],
selectedKeys || item.path
);
menuData.push(newItem);
else if(
!item.hideInMenu &&
!item.hideChildrenInMenu &&
item.children
)
menuData.push(...this.getMenuData(item.children, [...parentKeys, item.path]));
);
return menuData;
,
;
</script>
SubMenu.vue
<template functional>
<a-sub-menu :key="props.menuInfo.path">
<span slot="title">
<a-icon v-if="props.menuInfo.meta.icon" :type="props.menuInfo.meta.icon" />
<span> props.menuInfo.meta.title </span>
</span>
<template v-for="item in props.menuInfo.children">
<a-menu-item v-if="!item.children"
:key="item.path"
@click="() => parent.$router.push(path: item.path, query: parent.$router.query)"
>
<a-icon v-if="item.meta.icon" :type="item.meta.icon" />
<span> item.meta.title </span>
</a-menu-item>
<sub-menu v-else :key="item.path" :menu-info="item" />
</template>
</a-sub-menu>
</template>
<script>
export default
props: ["menuInfo"],
;
</script>
路由配置
import Vue from "vue";
import VueRouter from "vue-router";
import NProgress from "nprogress";
import "nprogress/nprogress.css";
import NotFound from "../views/404";
Vue.use(VueRouter);
const routes = [
path: "/user",
hideInMenu: true,
component: () =>
import(/* webpackChunkName: "layout" */ "../layouts/UserLayout"),
children: [
path: "/user",
redirect: "/user/login"
,
path: "/user/login",
name: "login",
component: () =>
import(/* webpackChunkName: "user" */ "../views/User/Login"),
,
path: "/user/register",
name: "register",
component: () =>
import(/* webpackChunkName: "user" */ "../views/User/Register"),
],
,
path: "/",
component: () =>
import(/* webpackChunkName: "layout" */ "../layouts/BasicLayout"),
children: [
path: "/",
redirect: "/dashboard"
,
path: "/dashboard",
redirect: "/dashboard/analysis"
,
path: "/dashboard",
name: "dashboard",
meta: icon: "dashboard", title: "仪表盘" ,
component: render: h => h("router-view"),
children: [
path: "/dashboard/analysis",
name: "analysis",
meta: title: "分析页" ,
component: () =>
import(/* webpackChunkName: "dashboard" */ "../views/Dashboard/Analysis"),
,
]
,
path: "/form",
name: "form",
meta: icon: "form", title: "表单" ,
component: render: h => h("router-view"),
children: [
path: "/form",
redirect: "/form/basic-form"
,
path: "/form/basic-form",
name: "basicform",
meta: title: "基础表单" ,
component: () =>
import(/* webpackChunkName: "form" */ "../views/Forms/BasicForm"),
,
path: "/form/step-form",
name: "stepform",
hideChildrenInMenu: true,
meta: title: "分步表单" ,
component: () =>
import(/* webpackChunkName: "form" */ "../views/Forms/StepForm"),
children: [
path: "/form/step-form",
redirect: "/form/step-form/info"
,
path: "/form/step-form/info",
name: "info",
component: () =>
import(/* webpackChunkName: "form" */ "../views/Forms/StepForm/Step1"),
,
path: "/form/step-form/confirm",
name: "confirm",
component: () =>
import(/* webpackChunkName: "form" */ "../views/Forms/StepForm/Step2"),
,
path: "/form/step-form/result",
name: "result",
component: () =>
import(/* webpackChunkName: "form" */ "../views/Forms/StepForm/Step3"),
,
]
,
]
],
,
path: "*",
name: "404",
hideInMenu: true,
component: NotFound
];
const router = new VueRouter(
mode: "history",
base: process.env.BASE_URL,
routes
);
// 路由守卫
router.beforeEach((to, from, next) =>
if(to.path !== from.path) 以上是关于Vue 开发实战实战篇 # 31:如何将菜单和路由结合的主要内容,如果未能解决你的问题,请参考以下文章
Vue 开发实战实战篇 # 29:如何设计一个高扩展性的路由
Vue 开发实战生态篇 # 20:选择何种模式的路由及底层原理