效果图
5-1 修改sidebar
sidebar组件中添加scrollPanel组件
src/layout/components/Sidebar/index.vue
<template><div class="sidebar-wrapper"><logo v-if="showLogo" :collapse="isCollapse" /><scroll-panel><el-menuclass="sidebar-container-menu":class="{'sidebar-show-logo': showLogo}"mode="vertical":default-active="activeMenu":background-color="scssVariables.menuBg":text-color="scssVariables.menuText":active-text-color="themeColor":collapse="isCollapse":collapse-transition="true"><sidebar-itemv-for="route in menuRoutes":key="route.path":item="route":base-path="route.path"/></el-menu></scroll-panel></div></template><script lang="ts">import { defineComponent, computed } from 'vue'import { useRoute } from 'vue-router'import variables from '@/styles/variables.scss'import { routes } from '@/router'import SidebarItem from './SidebarItem.vue'import { useStore } from '@/store'import Logo from './Logo.vue'import ScrollPanel from '@/components/ScrollPanel.vue'export default defineComponent({name: 'Sidebar',components: {Logo,SidebarItem,ScrollPanel},setup() {const route = useRoute()const store = useStore()// 根据路由路径 对应 当前激活的菜单const activeMenu = computed(() => {const { path, meta } = route// 可根据meta.activeMenu指定 当前路由激活时 让哪个菜单高亮选中if (meta.activeMenu) {return meta.activeMenu}return path})// scss变量const scssVariables = computed(() => variables)// 展开收起状态 稍后放store 当前是展开就让它收起const isCollapse = computed(() => !store.getters.sidebar.opened)// 渲染路由const menuRoutes = computed(() => routes)// 获取主题色const themeColor = computed(() => store.getters.themeColor)// 是否显示logoconst showLogo = computed(() => store.state.settings.sidebarLogo)return {// ...toRefs(variables), // 不有toRefs原因 缺点variables里面变量属性来源不明确scssVariables,isCollapse,activeMenu,menuRoutes,themeColor,showLogo}}})</script><style lang="scss" scoped>.sidebar-wrapper {.sidebar-container-menu {height: 100vh;&.sidebar-show-logo {height: calc(100vh - 50px);}}}</style>
5-2 scrollPanel组件
之前在tagsview文件夹里就有scrollPanel组件, 可以共用一个, 从layout/compoents/TagsView里 把ScrollPanel.vue移动到src/compoents里

src/layout/components/TagsView/index.vue 修改导入路径
5-3 随便添加点测试路由
src/router/index.ts
import { createRouter, createWebHashHistory, RouteRecordRaw } from 'vue-router'import Layout from '@/layout/index.vue'// 看作是异步获取路由export const asyncRoutes: Array<RouteRecordRaw> = [{path: '/documentation',component: Layout, // 布局组件作为一级路由redirect: '/documentation/index',children: [{path: 'index',name: 'Documentation',component: () => import(/* webpackChunkName: "documentation" */ '@/views/documentation/index.vue'),meta: {title: 'Documentation',icon: 'documentation',hidden: false, // 菜单栏不显示// 路由是否缓存 没有这个属性或false都会缓存 true不缓存noCache: false}}]},{path: '/guide',component: Layout,redirect: '/guide/index',children: [{path: 'index',name: 'Guide',component: () => import(/* webpackChunkName: "guide" */ '@/views/guide/index.vue'),meta: {title: 'Guide',icon: 'guide'// 当guide路由激活时高亮选中的是 documentation/index菜单// activeMenu: '/documentation/index'}}]},{path: '/system',component: Layout,redirect: '/system/user',meta: {title: 'System',icon: 'lock',alwaysShow: true // 根路由始终显示 哪怕只有一个子路由},children: [{path: 'menu',name: 'Menu Management',component: () => import(/* webpackChunkName: "menu" */ '@/views/system/menu.vue'),meta: {title: 'Menu Management',hidden: false,breadcrumb: false}},{path: 'role',name: 'Role Management',component: () => import(/* webpackChunkName: "role" */ '@/views/system/role.vue'),meta: {title: 'Role Management',hidden: false}},{path: 'user',name: 'User Management',component: () => import(/* webpackChunkName: "user" */ '@/views/system/user.vue'),meta: {title: 'User Management'}}]},{ // 外链路由path: '/external-link',component: Layout,children: [{path: 'https://www.baidu.com/',redirect: '/',meta: {title: 'External Link',icon: 'link'}}]},{ // 404一定放在要在最后面path: '/:pathMatch(.*)*',redirect: '/404',meta: {hidden: true}}]export const constantRoutes: Array<RouteRecordRaw> = [{path: '/',component: Layout,redirect: '/dashboard',children: [{path: 'dashboard',name: 'Dashboard',component: () => import(/* webpackChunkName: "dashboard" */ '@/views/dashboard/index.vue'),meta: {title: 'Dashboard',// icon: 'dashboard'icon: 'el-icon-platform-eleme',affix: true // 固定显示在tagsView中}}]},{path: '/redirect',component: Layout,meta: {hidden: true},children: [{ // 带参数的动态路由正则匹配// https://next.router.vuejs.org/zh/guide/essentials/route-matching-syntax.html#%E5%8F%AF%E9%87%8D%E5%A4%8D%E7%9A%84%E5%8F%82%E6%95%B0path: '/redirect/:path(.*)', // 要匹配多级路由 应该加*号component: () => import('@/views/redirect/index.vue')}]},{path: '/401',component: Layout,children: [{path: '',component: () => import('@/views/error-page/401.vue'),meta: {title: '401',icon: '404',hidden: true}}]},{path: '/404',component: () => import('@/views/error-page/404.vue'),meta: {hidden: true // 404 hidden掉}},// 以下都是测试路由 测完可以删了{path: '/menu',name: 'Menu Management1',component: () => import(/* webpackChunkName: "menu" */ '@/views/system/menu.vue'),meta: {title: 'Menu Management1',hidden: false,breadcrumb: false}},{path: '/role',name: 'Role Management1',component: () => import(/* webpackChunkName: "role" */ '@/views/system/role.vue'),meta: {title: 'Role Management1',hidden: false}},{path: '/user',name: 'User Management1',component: () => import(/* webpackChunkName: "user" */ '@/views/system/user.vue'),meta: {title: 'User Management1'}},{path: '/menu',name: 'Menu Management2',component: () => import(/* webpackChunkName: "menu" */ '@/views/system/menu.vue'),meta: {title: 'Menu Management2',hidden: false,breadcrumb: false}},{path: '/role',name: 'Role Management2',component: () => import(/* webpackChunkName: "role" */ '@/views/system/role.vue'),meta: {title: 'Role Management2',hidden: false}},{path: '/user',name: 'User Management2',component: () => import(/* webpackChunkName: "user" */ '@/views/system/user.vue'),meta: {title: 'User Management2'}},{path: '/menu',name: 'Menu Management3',component: () => import(/* webpackChunkName: "menu" */ '@/views/system/menu.vue'),meta: {title: 'Menu Management3',hidden: false,breadcrumb: false}},{path: '/role',name: 'Role Management3',component: () => import(/* webpackChunkName: "role" */ '@/views/system/role.vue'),meta: {title: 'Role Management4',hidden: false}},{path: '/user',name: 'User Management3',component: () => import(/* webpackChunkName: "user" */ '@/views/system/user.vue'),meta: {title: 'User Management3'}},{path: '/menu',name: 'Menu Management4',component: () => import(/* webpackChunkName: "menu" */ '@/views/system/menu.vue'),meta: {title: 'Menu Management4',hidden: false,breadcrumb: false}},{path: '/role',name: 'Role Management4',component: () => import(/* webpackChunkName: "role" */ '@/views/system/role.vue'),meta: {title: 'Role Management4',hidden: false}},{path: '/user',name: 'User Management4',component: () => import(/* webpackChunkName: "user" */ '@/views/system/user.vue'),meta: {title: 'User Management4'}},{path: '/role',name: 'Role Management5',component: () => import(/* webpackChunkName: "role" */ '@/views/system/role.vue'),meta: {title: 'Role Management5',hidden: false}},{path: '/user',name: 'User Management5',component: () => import(/* webpackChunkName: "user" */ '@/views/system/user.vue'),meta: {title: 'User Management5'}}]export const routes = [...constantRoutes,...asyncRoutes]const router = createRouter({history: createWebHashHistory(),routes})export default router
测试完滚动 测试的路由都可以删了

