说明
【Vue 开发实战】学习笔记。
实现效果
BasicLayout.vue
<template>
<div :class="[`nav-theme-${navTheme}`, `nav-layout-${navLayout}`]">
<a-layout id="components-layout-demo-side" style="min-height:">
<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:">
<a-icon
class="trigger"
:type="collapsed ? 'menu-unfold' : 'menu-fold'"
@click="collapsed = !collapsed"
></a-icon>
<Header />
</a-layout-header>
<a-layout-content style="margin:">
<router-view></router-view>
</a-layout-content>
<a-layout-footer style="text-align:">
<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:">
<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 = [],) {
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,) => {
if(to.path !== from.path) {
NProgress.start();
}
next();
})
router.afterEach((to, from) => {
NProgress.done();
})
export default router;
参考
https://github.com/vueComponent/ant-design-vue/blob/1.4.0/components/menu/demo/SubMenu.vue