效果图
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-menu
class="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-item
v-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)
// 是否显示logo
const 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%B0
path: '/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
测试完滚动 测试的路由都可以删了