赞
踩
前提条件:组件创建完成
// src/router/index.ts import { createRouter, createWebHashHistory } from 'vue-router' import type { RouteRecordRaw } from 'vue-router' export const Layout = () => import('@/layout/index.vue') // 静态路由 export const routes: RouteRecordRaw[] = [ { path: '/login', component: () => import('@/views/login/index.vue'), hidden: true }, { path: '/401', component: () => import('@/views/error-page/401.vue'), hidden: true }, { path: '/404', component: () => import('@/views/error-page/404.vue'), hidden: true }, { path: '/', component: Layout, redirect: '/home', children: [ { path: 'home', component: () => import('@/views/home/index.vue'), name: 'Home', meta: { title: '首页', icon: 'home' } } ] }, { path: '/permission', component: Layout, meta: { title: '权限管理', icon: 'permission' }, children: [ { path: 'user', component: () => import('@/views/permission/user/index.vue'), name: 'User', meta: { title: '用户管理'} }, { path: 'role', component: () => import('@/views/permission/role/index.vue'), name: 'Role', meta: { title: '角色管理' } } ] } ] const router = createRouter({ history: createWebHashHistory(), routes: routes as RouteRecordRaw[], scrollBehavior: () => ({ left: 0, top: 0 }) }) /** * 重置路由 */ export function resetRouter() { router.replace({ path: '/login' }) } export default router
目录结构
sidebar/index.vue
<script lang="ts" setup> // sidebarItem 项组件 import SideBarItem from './sidebarItem.vue' import { useRouter } from 'vue-router' import { usePermissionStoreHook } from '@/stores/permission' import { toRaw } from 'vue' // 拿到路由列表,过滤我们不想要的 const router = useRouter() const permissionStore = usePermissionStoreHook() const routerList = toRaw(permissionStore.permission.routes) console.log(routerList, '获取到的路由list') const defaultOpenList = [] const activeMenu = ref() function handleSelect(index, indexPath) { console.log(index, indexPath) } watch( () => router.currentRoute.value.path, (toPath) => { activeMenu.value = toPath //要执行的方法 console.log(toPath) }, { immediate: true, deep: true } ) </script> <template> <div class="sidebar"> <!-- 导航菜单 --> <el-menu ref="elMenu" :default-active="activeMenu" @select="handleSelect" :default-openeds="defaultOpenList" router > <!-- 引入子组件 --> <SideBarItem :routerList="routerList" /> </el-menu> </div> </template> <style lang="scss" scoped> .sidebar { height: 100%; padding-top: 30px; :deep(.el-menu) { width: 100%; height: 100%; overflow-y: auto; background: transparent; border: none; .el-menu-item { font-size: 16px; height: 25px; padding: 0 30px; margin-bottom: 40px; background: transparent; display: flex; align-items: center; outline: none; box-sizing: border-box; &:last-child { margin-bottom: 0; } img { width: 24px; height: 24px; margin-right: 10px; } span { color: var(--vt-main-color); } &.is-active { position: relative; span { color: var(--vt-main-color); font-weight: 600; font-family: 'PingFangSC-Semibold'; } &::after { content: ''; position: absolute; width: 4px; height: 30px; background: #2b5ae8; left: 0; top: 0; bottom: 0; margin: auto; z-index: 999; } } } .el-sub-menu { font-size: 14px; margin-bottom: 40px; .el-menu-item { min-width: 179px; padding: 0 64px !important; outline: none; overflow: hidden; font-size: 14px; margin-bottom: 20px; &:last-child { margin-bottom: 0; } &:first-child { margin-top: 20px; } span { color: #797979; } &.is-active { span { font-family: 'PingFangSC-Semibold'; font-weight: 600; color: var(--vt-main-color); } } } &.is-opened { .el-submenu__title { > span { color: var(--vt-main-color); } } &.is-active { .el-submenu__title { font-weight: 600; } } } .el-sub-menu__title { font-size: 16px; height: 25px; display: flex; align-items: center; padding: 0 30px !important; background: transparent; img { width: 24px; height: 24px; margin-right: 10px; } &:hover { background: transparent; } + .el-menu { .el-submenu__title { background: transparent; padding: 0 64px !important; } .el-submenu { .el-menu { .el-menu-item { padding: 0 100px !important; &.is-active { padding: 0 100px !important; } } } } } // span { // position: relative; // &::after { // content: ''; // @include imageURL('closeMenu.png'); // width: vw(5 * 2); // height: vw(5 * 2); // position: absolute; // right: vw(-15 * 2); // top: 0; // bottom: 0; // margin: auto; // } // } } .el-sub-menu__icon-arrow { display: none; } &.is-opened { > .el-sub-menu__title { &:hover { background: transparent; } } .el-menu-item { padding: 0 64px !important; &.is-active { padding-left: 64px !important; font-weight: 600; color: var(--vt-main-color); } } } .el-submenu { margin-bottom: 20px; &:first-child { margin-top: 20px; } } } } } </style>
<script lang="ts" setup> defineProps({ routerList: { type: Array, default: () => { return [] } } }) const getImageUrl = (iconName) => { return new URL(`../../../assets/menu/${iconName}.png`, import.meta.url).href } </script> <template> <template v-for="menu in routerList"> <el-sub-menu :key="menu.url" :index="menu.url" v-if="menu.children && menu.children.length > 0 && !menu.hidden" > <template #title> <img :src="getImageUrl(menu.meta.icon)" alt="" /> <span class="menu-title">{{ menu.meta.title }}</span> </template> <sidebarItem :router-list="menu.children"></sidebarItem> </el-sub-menu> <el-menu-item :key="menu.meta.url + 'u'" :index="menu.meta.url" v-else-if="!menu.hidden"> <img :src="getImageUrl(menu.meta.icon)" alt="" v-if="menu.meta.icon" /> <span class="menu-title">{{ menu.meta.title }}</span> </el-menu-item> </template> </template>
<template> <div class="page-box"> <div class="page-left"> <div class="logo-box"> <img src="@/assets/menu/logo-word.png" alt="" /> </div> <sidebar class="side-menu"></sidebar> </div> <div class="page-right"> <div class="header-box"> <div class="title">让电看得见摸得着.</div> </div> <Layout></Layout> </div> </div> </template> <script setup lang="ts"> import Layout from './layout.vue' import sidebar from './components/sidebar/index.vue' </script> <style lang="scss" scoped> .page-box { width: 100%; height: 100%; display: flex; overflow: hidden; position: relative; background: #f0f0f0; .page-left { width: 258px; position: fixed; left: 6px; top: 0; bottom: 0; margin: auto; display: flex; flex-direction: column; background: #f0f0f0; .logo-box { height: 73px; display: flex; align-items: center; padding-left: 34px; width: 100%; img { width: 73px; height: 30px; } } .side-menu { width: 100%; flex: 1; background: url('@/assets/menu/bg.png') no-repeat; background-size: 100% 100%; overflow: hidden; transition: width 0.28s; margin-bottom: 60px; box-sizing: content-box; } } .page-right { flex: 1; height: 100%; transition: margin-left 0.28s; margin-left: 264px; display: flex; flex-direction: column; .header-box { position: fixed; width: 87.0625%; //210-230 left: 260px; top: 0; padding: 0 50px; display: flex; align-items: center; height: 73px; justify-content: space-between; box-sizing: border-box; z-index: 9; } } } </style>
<template> <div id="app-main"> <router-view v-slot="{ Component, route }"> <transition name="router-fade" mode="out-in"> <div key="route.fullPath"> <component :is="Component" /> </div> </transition> </router-view> </div> </template> <script setup lang="ts"></script> <style lang="scss"> #app-main { flex: 1; height: 100%; padding-top: 73px; display: flex; -webkit-box-orient: vertical; -webkit-box-direction: normal; -ms-flex-direction: column; flex-direction: column; padding-left: 40px; } </style>
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。