vue3后台管理系统页面搭建(左侧菜单栏+右侧内容)

449 阅读1分钟

1.页面布局展示

image.png

2.开始实现

(1)App页面(根页面)

<script setup lang="ts">
import Layout from './components/Layout.vue';
</script>

<template>
    <Layout>
        // router-view 通过slot放出来,方便后期改造(比如 keep-alive什么的)
        <router-view />
    </Layout>
</template>

<style lang="less" scoped></style>

(2) layout实现

<script setup lang="ts">
import Aside from './aside/index.vue';
</script>

<template>
    <section class="h-full flex">
        <Aside />
        <div class="flex-1 overflow-hidden">
            <slot></slot>
        </div>
    </section>
</template>

<style lang="less" scoped></style>

(3)Aside 实现(一个展示页面 + 一个 可无限嵌套的menuList组件)

一. Aside主页面实现

<script lang="ts">
// 为了让组件名字展示成Aside(而不是index),网上查了一下 需要安装 unplugin-vue-define-options 才给 setup 语法糖用,想了想这个也可以接受
export default {
    name: 'Aside',
};
</script>
<script lang="ts">
export default {
    name: 'Aside',
};
</script>
<script setup lang="ts">
import { ref, watchPostEffect } from 'vue';
import { routes } from '../../router/index';

import MenuList from './MenuList.vue';
import { useRoute } from 'vue-router';

const isCollapse = ref(false);
const defaultActive = ref('/');
const route = useRoute();

watchPostEffect(() => {
    defaultActive.value = route.path;
});
</script>

<template>
    <section class="h-full flexcol">
        <el-menu
            class="flex-1"
            router
            :collapse="isCollapse"
            active-text-color="#ffd04b"
            background-color="#545c64"
            :default-active="defaultActive"
            text-color="#fff"
        >
            <MenuList :menus="routes"></MenuList>
        </el-menu>
        <el-button type="primary" @click="isCollapse = !isCollapse">
            <el-icon v-if="!isCollapse"><ArrowRightBold /></el-icon>
            <el-icon v-else><ArrowLeftBold /></el-icon>
        </el-button>
    </section>
</template>

<style lang="less" scoped></style>

二. 嵌套menuList组件实现

<script setup lang="ts">
import { RouteRecordRaw } from 'vue-router';

interface PropsVO {
    menus: RouteRecordRaw[] | [];
}

withDefaults(defineProps<PropsVO>(), {
    menus: () => [],
});
</script>

<template>
    <template v-for="menu in menus">
        <!-- 类型为菜单时,使用 el-sub-menu  -->
        <el-sub-menu
            v-if="menu.meta!.isShow && menu.children && menu.children.length"
            :key="menu.path + 'submenu'"
            :index="menu.path"
        >
            <template #title>
                <el-icon><location /></el-icon>
                <span>{{ menu.meta!.name }}</span>
            </template>
            <!-- 只有菜单有下级,所以放在这个位置 -->
            <menu-list :menus="menu.children"></menu-list>
        </el-sub-menu>
        <!-- 类型为功能时,使用 el-menu-item -->
        <template v-else>
            <el-menu-item v-if="menu.meta!.isShow" :key="menu.path + 'item'" :index="menu.path">
                <el-icon><location /></el-icon>
                <template #title>{{ menu.meta!.name }}</template>
            </el-menu-item>
        </template>
    </template>
</template>

附加一个路由吧

import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router';
import HomeView from '../views/HomeView.vue';

// meta中isShow 是否展示菜单    meta中name  菜单的名字   meta可以加一个icon,用作前面的小图标

export const routes: Array<RouteRecordRaw> = [
    {
        path: '/',
        meta: {
            isShow: false, 
        },
        redirect: {
            path: '/home',
        },
    },
    {
        path: '/home',
        name: 'home',
        meta: {
            name: '首页',
            isShow: true,
        },
        component: HomeView,
    },
    {
        path: '/about',
        name: 'about',
        meta: {
            name: 'about',
            isShow: true,
        },
        component: () => import(/* webpackChunkName: "about" */ '../views/AboutView.vue'),
    },
];

const router = createRouter({
    history: createWebHistory(process.env.BASE_URL),
    routes,
});

export default router;

附上仓库代码 github.com/maqianbo-we… ,有问题,或者宝贵意见的小伙伴欢迎评论,赠人玫瑰,手留余香,如果对您有帮助,希望帮忙点个赞,谢谢!!!