demo地址:https://gitee.com/shjin/menu_...
1.创立vue
我的项目
vue create menu_demo
2.装置ant-design-vue
yarn add ant-design-vue
3.main.js
文件引入ant-design-vue
import Antd from 'ant-design-vue';import 'ant-design-vue/dist/antd.css';Vue.use(Antd);
4.菜单index.js
import Menu from "ant-design-vue/es/menu";import Icon from "ant-design-vue/es/icon";const { Item, SubMenu } = Menu;export default { name: "SMenu", props: { menu: { type: Array, required: true }, theme: { type: String, required: false, default: "light" }, mode: { type: String, required: false, default: "inline" }, collapsed: { type: Boolean, required: false, default: false }, }, data() { return { openKeys: [], cachedOpenKeys: [], selectedKeys:['user1'] }; }, computed: { rootSubmenuKeys: vm => { const keys = []; vm.menu.forEach(item => keys.push(item.path)); return keys; } }, mounted() { this.updateMenu(); }, watch: { collapsed(val) { if (val) { this.cachedOpenKeys = this.openKeys.concat(); this.openKeys = []; } else { this.openKeys = this.cachedOpenKeys; } }, $route: function() { this.updateMenu(); } }, methods: { // select menu item onOpenChange(openKeys) { // 在程度模式下时执行,并且不再执行后续 if (this.mode === "horizontal") { this.openKeys = openKeys; return; } // 非程度模式时 const latestOpenKey = openKeys.find(key => !this.openKeys.includes(key)); if (!this.rootSubmenuKeys.includes(latestOpenKey)) { this.openKeys = openKeys; } else { this.openKeys = latestOpenKey ? [latestOpenKey] : []; } }, updateMenu() { const routes = this.$route.matched.concat(); const { hidden } = this.$route.meta; if (routes.length >= 3 && hidden) { routes.pop(); this.selectedKeys = [routes[routes.length - 1].path]; } else { this.selectedKeys = [routes.pop().path]; } const openKeys = []; if (this.mode === "inline") { routes.forEach(item => { openKeys.push(item.path); }); } //update-begin-author:taoyan date:20190510 for:online表单菜单点击开展的一级目录不对 if (!this.selectedKeys || this.selectedKeys[0].indexOf(":") < 0) { this.collapsed ? (this.cachedOpenKeys = openKeys) : (this.openKeys = openKeys); } //update-end-author:taoyan date:20190510 for:online表单菜单点击开展的一级目录不对 }, // render renderItem(menu) { if (!menu.hidden) { return menu.children && !menu.alwaysShow ? this.renderSubMenu(menu) : this.renderMenuItem(menu); } return null; }, renderMenuItem(menu) { let props = { to: { name: menu.name } }; const attrs = { target: menu.target }; return ( <Item {...{ key: menu.key }}> <div {...{ props, attrs }} > {this.renderIcon(menu.icon)} <span>{menu.title}</span> </div> </Item> ); }, renderSubMenu(menu) { const itemArr = []; if (!menu.alwaysShow) { menu.children.forEach(item => itemArr.push(this.renderItem(item))); } return ( <SubMenu {...{ key: menu.key }}> <span slot="title"> {this.renderIcon(menu.icon)} <span>{menu.title}</span> </span> {itemArr} </SubMenu> ); }, renderIcon(icon) { if (icon === "none" || icon === undefined) { return null; } const props = {}; typeof icon === "object" ? (props.component = icon) : (props.type = icon); return <Icon {...{ props }} />; } }, render() { const { mode, theme, menu } = this; const props = { mode: mode, theme: theme, openKeys: this.openKeys }; const on = { select: obj => { this.selectedKeys = obj.selectedKeys; this.$emit("select", obj); }, openChange: this.onOpenChange }; const menuTree = menu.map(item => { if (item.hidden) { return null; } return this.renderItem(item); }); return ( <Menu vModel={this.selectedKeys} {...{ props, on: on }}> {menuTree} </Menu> ); }};
5.联合应用
<template> <div> <a-layout id="components-layout-demo-custom-trigger"> <a-layout-sider v-model="collapsed" :trigger="null" collapsible :style="{ overflow: 'auto', height: '100vh', position: 'fixed', left: 0, zIndex: 2, }" > <s-menu class="my-menu" :menu="treeData" theme="dark" ref="sMenu" mode="inline" :selectedKeys="selectedKeys" @select="onSelect" :collapsed="collapsed" collapseible > </s-menu> </a-layout-sider> <a-layout :style="{ marginLeft: collapsed ? '80px' : '200px' }"> <a-layout-header style="background: #fff; padding: 0," :style="{ position: 'fixed', zIndex: 1, width: '100%' }" > <a-icon class="trigger" :type="collapsed ? 'menu-unfold' : 'menu-fold'" @click="() => (collapsed = !collapsed)" /> </a-layout-header> <div :style="{ position: 'fixed', zIndex: 1, width: '100%', background: '#fff', top:'70px' }" > <a-tabs v-model="activeKey" @prevClick="callback" @nextClick="callback" @tabClick="menuClick" type="card" > <a-tab-pane v-for="(pane, index) in menuList" :key="pane.key"> <span slot="tab" class="item-pane"> {{ pane.title }} <a-icon v-if="index !== 0" type="close" class="pane-close" @click.stop="closeMenu(index, pane)" /> </span> </a-tab-pane> </a-tabs> </div> <a-layout-content :style="{ margin: '134px 16px 24px 16px', padding: '24px', background: '#fff', minHeight: '280px', height: 'calc(100vh - 160px)', overflow: 'auto', }" > <div style="height:600px">Content</div> </a-layout-content> </a-layout> </a-layout> </div></template><script>import SMenu from "@/components/index";export default { components: { SMenu }, data() { return { collapsed: false, activeKey: "user1", //以后菜单key expandedKeys: [], selectedKeys: ["user1"], autoExpandParent: true, menuList: [{ key: "user1", title: "用户1" }], treeData: [ { title: "用户1", key: "user1", icon: "user", }, { title: "媒体", key: "video-camera", icon: "video-camera", children: [ { title: "上传", key: "upload", }, { title: "下载", key: "download", children: [ { title: "下载2", key: "download2", }, ], }, ], }, ], }; }, methods: { // 抉择树节点 onSelect(event) { let key = event.key; this.activeKey = key; this.selectedKeys = [key]; let title = this.getTitle(this.treeData, key); let filterMenu = this.menuList.filter((menu) => menu.key == key); if (!filterMenu.length) this.menuList.push({ key, title }); }, getTitle(data, value) { let title; for (let i = 0; i < data.length; i++) { let item = data[i]; if (item && item.key == value) { title = item.title; } else if (item.children && item.children.length) { if (this.getTitle(item.children, value)) { title = this.getTitle(item.children, value); } } } return title; }, menuClick(val) { this.selectedKeys = [val]; this.$refs.sMenu.selectedKeys = this.selectedKeys; }, // 敞开标签 closeMenu(index, item) { this.menuList.splice(index, 1); if (this.activeKey == item.key) { this.activeKey = this.menuList[index - 1].key; this.selectedKeys = [this.activeKey]; } console.log(item); }, callback(val) { console.log(val); }, },};</script><style scoped>.ant-layout-header { padding: 0;}#components-layout-demo-custom-trigger .trigger { font-size: 18px; line-height: 64px; padding: 0 24px; cursor: pointer; transition: color 0.3s;}#components-layout-demo-custom-trigger .trigger:hover { color: #1890ff;}</style>
6.效果图