当前位置: 首页 > news >正文

vue3 学习笔记17 -- 基于el-menu封装菜单

vue3 学习笔记17 – 基于el-menu封装菜单

前提条件:组件创建完成

配置路由

// 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

封装el-menu

  • 目录结构
    在这里插入图片描述

  • 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-menuref="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>
  • sidebar/siderbarItem.vue
<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>
  • layout/index.vue – 引入菜单
<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-230left: 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>
  • layout/lauout.vue
<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>
  • 运行项目查看页面
http://www.lryc.cn/news/408047.html

相关文章:

  • 使用 Redis 实现验证码、token 的存储,用自定义拦截器完成用户认证、并使用双重拦截器解决 token 刷新的问题
  • 反转链表 - 力扣(LeetCode)C语言
  • 【Linux】进程间通信(1):进程通信概念与匿名管道
  • Spring从入门到精通 01
  • C语言经典习题25
  • 2-47 基于matlab的时域有限差分法(FDTD法)拉夫等效原理进行时谐场外推
  • JupyterNotebook快捷键 自用
  • 【我的OpenGL学习进阶之旅】讲一讲GL_TEXTURE_2D和GL_TEXTURE_EXTERNAL_OES的区别
  • Makefile 如何将生成的 .o 文件放到指定文件夹
  • 聊一聊知识图谱结合RAG
  • Java面试锦集 之 一、Java基础(1)
  • 【leetcode】排列序列
  • 【Cesium开发实战】视频融合功能的实现,可自定义位置和视频路径
  • 【秋招笔试题】小明的美食
  • 基于OpenLCA、GREET、R语言的生命周期评价方法、模型构建及典型案例应用
  • Linux操作系统 -socket网络通信
  • 【苍穹】完美解决由于nginx更换端口号导致无法使用Websocket
  • Qt中在pro中实现一些宏定义
  • bash XXX.sh文件和直接运行XXX.sh的区别
  • 【Python机器学习】k-近邻算法简单实践——改进约会网站的配对效果
  • vue3前端开发-小兔鲜项目-登录组件的开发表单验证
  • Winform上位机TCP客户端/服务端、串口通信
  • Linux基础复习(二)
  • nginx漏洞修复 ngx_http_mp4_module漏洞(CVE-2022-41742)【低可信】 nginx版本升级
  • 网格布局 HTML CSS grid layout demo
  • Java算法之递归算法-如何计算阶乘的值
  • python爬虫入门小案例
  • 【昇腾AI创新大赛集训营南京站学习笔记】-Ascend算子开发课程
  • 系统架构设计师教程 第4章 信息安全技术基础知识-4.5 密钥管理技术4.6 访问控制及数字签名技术-解读
  • C语言日常练习Day13