vue做动态路由时,侧边栏采用递归组件加载嵌套路由

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.基本操作,不用起立

  • 7
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值