本节目标

image.png

点击收起
image.png

1-1创建Sidebar组件

src/layout/components/Sidebar/index.vue
image.png

将layout/index.vue中导入组件
image.png

  1. <template>
  2. <div class="app-wrapper">
  3. <div class="sidebar-container">
  4. <Sidebar />
  5. </div>
  6. <div class="main-container">
  7. <div class="header">
  8. <div class="navbar">navbar</div>
  9. <div class="tags-view">tagsview</div>
  10. </div>
  11. <div class="app-main">
  12. <h2>app main</h2>
  13. <router-view></router-view>
  14. </div>
  15. </div>
  16. </div>
  17. </template>
  18. <script>
  19. import Sidebar from './components/Sidebar'
  20. export default {
  21. components: {
  22. Sidebar
  23. }
  24. }
  25. </script>
  26. <style lang="scss" scoped>
  27. .app-wrapper {
  28. display: flex;
  29. width: 100%;
  30. height: 100%;
  31. .main-container {
  32. flex: 1;
  33. display: flex;
  34. flex-direction: column;
  35. .header {
  36. background: cyan;
  37. .navbar {
  38. height: 50px;
  39. background: #1890ff;
  40. }
  41. .tags-view {
  42. height: 34px;
  43. background: #12efff;
  44. }
  45. }
  46. .app-main {
  47. /* 50= navbar 50 如果有tagsview + 34 */
  48. min-height: calc(100vh - 84px);
  49. background: red;
  50. }
  51. }
  52. }
  53. </style>

1.element.ts导入所需菜单组件

这里主要会用到 el-menu el-menu-item element组件 大家别忘了导入
image.png

2.sidebar中菜单组件属性配置

src/layout/components/Sidebar/index.vue

  1. <template>
  2. <div>
  3. <!-- 测试展开收起 -->
  4. <h8 @click="isCollapse=!isCollapse">展收测试</h8>
  5. <el-menu
  6. class="sidebar-container-menu"
  7. mode="vertical"
  8. :default-active="activeMenu"
  9. :background-color="scssVariables.menuBg"
  10. :text-color="scssVariables.menuText"
  11. :active-text-color="scssVariables.menuActiveText"
  12. :collapse="isCollapse"
  13. :collapse-transition="true"
  14. >
  15. <sidebar-item />
  16. </el-menu>
  17. </div>
  18. </template>
  19. <script lang="ts">
  20. import { defineComponent, computed, ref } from 'vue'
  21. import { useRoute } from 'vue-router'
  22. // 导入scss变量在组件中使用
  23. import variables from '@/styles/variables.scss'
  24. // el-menu-item封装
  25. import SidebarItem from './SidebarItem.vue'
  26. export default defineComponent({
  27. name: 'Sidebar',
  28. components: {
  29. SidebarItem
  30. },
  31. setup() {
  32. const route = useRoute()
  33. // 根据路由路径 对应 当前激活的菜单 页面刷新后 激活当前路由匹配的菜单
  34. const activeMenu = computed(() => {
  35. const { path } = route
  36. return path
  37. })
  38. // scss变量
  39. const scssVariables = computed(() => variables)
  40. // 菜单展开收起状态 后面会放store里
  41. const isCollapse = ref(true)
  42. return {
  43. // ...toRefs(variables), // 不有toRefs原因 缺点variables里面变量属性来源不明确
  44. scssVariables,
  45. isCollapse,
  46. activeMenu
  47. }
  48. }
  49. })
  50. </script>

3. 封装SidebarItem组件

src/layout/components/Sidebar/SidebarItem.vue
目前里面只有一个菜单项 大家可以测下菜单展开收起

  1. <template>
  2. <div class="sidebar-item-container">
  3. <el-menu-item index="1">
  4. <svg-icon class="menu-icon" icon-class="lock"></svg-icon>
  5. <template #title>
  6. <span>Dashoard</span>
  7. </template>
  8. </el-menu-item>
  9. </div>
  10. </template>
  11. <script lang="ts">
  12. import { defineComponent } from 'vue'
  13. export default defineComponent({
  14. name: 'SidebarItem'
  15. })
  16. </script>
  17. <style lang="scss">
  18. .sidebar-item-container {
  19. .menu-icon {
  20. margin-right: 16px;
  21. margin-left: 5px;
  22. vertical-align: middle;
  23. }
  24. }
  25. </style>

4. sidebar 全局css样式改动

image.png

  1. #app {
  2. .sidebar-container {
  3. width: $sideBarWidth !important;
  4. height: 100%;
  5. background-color: pink;
  6. background-color: $menuBg;
  7. // menu未收起时样式
  8. &-menu:not(.el-menu--collapse) {
  9. width: $sideBarWidth;
  10. }
  11. .el-menu {
  12. border: none;
  13. }
  14. }
  15. }

5.简单创建几个路由页

内容很简单
image.png
image.png

6.路由注册下

路由一级都是layout组件

  1. import { createRouter, createWebHashHistory, RouteRecordRaw } from 'vue-router'
  2. import Layout from '@/layout/index.vue'
  3. // 看作是异步获取路由
  4. export const asyncRoutes: Array<RouteRecordRaw> = [
  5. {
  6. path: '/documentation',
  7. component: Layout, // 布局组件作为一级路由
  8. redirect: '/documentation/index',
  9. children: [
  10. {
  11. path: 'index',
  12. name: 'Documentation',
  13. component: () => import(/* webpackChunkName: "documentation" */ '@/views/documentation/index.vue'),
  14. meta: {
  15. title: 'Documentation',
  16. icon: 'documentation'
  17. }
  18. }
  19. ]
  20. },
  21. {
  22. path: '/guide',
  23. component: Layout,
  24. redirect: '/guide/index',
  25. children: [
  26. {
  27. path: 'index',
  28. name: 'Guide',
  29. component: () => import(/* webpackChunkName: "guide" */ '@/views/guide/index.vue'),
  30. meta: {
  31. title: 'Guide',
  32. icon: 'guide'
  33. }
  34. }
  35. ]
  36. },
  37. {
  38. path: '/system',
  39. component: Layout,
  40. redirect: '/system/user',
  41. meta: {
  42. title: 'System',
  43. icon: 'lock'
  44. },
  45. children: [
  46. {
  47. path: 'menu',
  48. component: () => import(/* webpackChunkName: "menu" */ '@/views/system/menu.vue'),
  49. meta: {
  50. title: 'Menu Management',
  51. icon: 'list'
  52. }
  53. },
  54. {
  55. path: 'role',
  56. component: () => import(/* webpackChunkName: "role" */ '@/views/system/role.vue'),
  57. meta: {
  58. title: 'Role Management',
  59. icon: 'list'
  60. }
  61. },
  62. {
  63. path: 'user',
  64. component: () => import(/* webpackChunkName: "user" */ '@/views/system/user.vue'),
  65. meta: {
  66. title: 'User Management',
  67. icon: 'list'
  68. }
  69. }
  70. ]
  71. }
  72. ]
  73. export const constantRoutes: Array<RouteRecordRaw> = [
  74. {
  75. path: '/',
  76. component: Layout,
  77. redirect: '/dashboard',
  78. children: [
  79. {
  80. path: 'dashboard',
  81. name: 'Dashboard',
  82. component: () => import(/* webpackChunkName: "dashboard" */ '@/views/dashboard/index.vue'),
  83. meta: {
  84. title: 'Dashboard'
  85. }
  86. }
  87. ]
  88. }
  89. ]
  90. export const routes = [
  91. ...constantRoutes, // 解构语法可能报波浪线tslib版本升级 没懂 暂时先不管
  92. ...asyncRoutes
  93. ]
  94. const router = createRouter({
  95. history: createWebHashHistory(),
  96. routes
  97. })
  98. export default router

本节源码参考

https://gitee.com/brolly/vue3-element-admin/commit/7411683e2923767adb62b051b0f9a6d12cc907e5