1.翻博客时,看到很多人在做路由权限,加载侧边菜单栏时,会报各种错误,比如:
Cannot read properties of undefined (reading 'propsData')"
2.下面演示如何正确使用递归组件,实现渲染嵌套菜单栏
3.先在main.js引入ant-design-vue组件库,我这里是按需加载。
//ant-design-vue按需加载
import { Layout, Menu, Icon, Button } from "ant-design-vue";
Vue.use(Layout)
.use(Button)
Vue.component(Menu.name, Menu);
Vue.component(Icon.name, Icon);
Vue.component(Menu.Item.name, Menu.Item);
Vue.component(Menu.SubMenu.name, Menu.SubMenu);
4.本地模拟嵌套路由,routes.js文件
export const routes = [
{
path: '/guidePage',
name: 'guidePage',
components: () => import(/* webpackChunkName: "tabLayout" */ '../views/guidePage/guidePage.vue'),
title: '引导页',
icon: 'file-sync',
key: 'k-1-1',
children: [
{
path: '/subGuide',
name: 'subGuide',
components: () => import(/* webpackChunkName: "subGuide" */ '../views/subGuide/subGuide.vue'),
title: '二级引导',
icon: 'file-sync',
key: 'k-1-1-1'
}
]
},
{
path: '/employeesList',
name: 'employeesList',
components: () => import(/* webpackChunkName: "employeesList" */ '../views/employeesList/employeesList.vue'),
title: '员工列表',
icon: 'file-sync',
key: 'k-1-2',
children: []
}
]
5,配置好路由
import Vue from 'vue'
import VueRouter from 'vue-router'
import { routes } from "./routes";
Vue.use(VueRouter)
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes: [
{
path: '/',
name: 'tabLayout',
component: () => import(/* webpackChunkName: "tabLayout" */ '../views/tabLayout/tabLayout.vue'),
title: 'layout页面',
icon: 'file-sync',
key: 'k-1',
children: [...routes]
}
]
})
export default router
6.在父组件中使用
<template>
<a-layout id="components-layout-demo-custom-trigger">
<a-layout-sider v-model="collapsed" :trigger="null" collapsible>
<div class="logo">
<div class="text" title="by ant-design-vue@1">
by ant-design-vue@1
</div>
</div>
<a-menu theme="dark" mode="inline">
<template v-for="item in routes">
<!-- 根节点,无子节点的情况 -->
<a-menu-item v-if="!item.children.length" :key="item.key">
<a-icon type="pie-chart" />
<span>{{ item.title }}</span>
</a-menu-item>
<!-- 有子节点,有children的使用可折叠-->
<subMenu v-else :key="item.key" :menuInfo="item"></subMenu>
</template>
</a-menu>
</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-layout-header>
<a-layout-content :style="{ margin: '24px 16px', padding: '24px', background: '#fff', minHeight: '280px' }">
<router-view></router-view>
</a-layout-content>
</a-layout>
</a-layout>
</template>
<script>
import { routes } from "@/router/routes";
import subMenu from "@/components/subMenu/subMenu.vue";
export default {
name: 'tabLayout',
components: {
subMenu
},
data() {
return {
collapsed: false,
routes
}
}
};
</script>
<style scoped lang="less">
.ant-layout {
height: 100%;
.logo {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
color: #fff;
text-align: center;
font-family: "logoFont";
font-size: 18px;
.text {
width: 100%;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
cursor: pointer;
}
}
}
#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;
}
#components-layout-demo-custom-trigger .logo {
height: 32px;
background: rgba(255, 255, 255, 0.2);
margin: 16px;
}
</style>
7.subMenu子组件:
<template>
<a-sub-menu :key="menuInfo.key" v-bind="$props" v-on="$listeners">
<span slot="title">
<a-icon type="mail" />
<span>{{ menuInfo.title }}</span>
</span>
<template v-for="item in menuInfo.children">
<!-- 根节点,无子节点情况 -->
<a-menu-item v-if="item.children == void 0 || item.children.length == 0" :key="item.key">
<a-icon type="pie-chart" />
<span>{{ item.title }}</span>
</a-menu-item>
<!-- 有子节点,有children的使用可折叠递归组件 -->
<subMenu v-else :key="item.key" :menuInfo="item" />
</template>
</a-sub-menu>
</template>
<script>
import { Menu } from 'ant-design-vue';
export default {
name: "subMenu",
isSubMenu: true,
components:{
},
props: {
...Menu.SubMenu.props,
menuInfo: {
type: Object,
default: () => ({})
}
}
}
</script>
<style scoped lang="less"></style>
8.看效果
9.在添加一级路由测试效果
10.基本操作,不用起立