后台管理系统-3-vue3之左侧菜单栏和头部导航栏的静态搭建
文章目录
- 1 CommonAside组件(静态搭建)
- 1.1 Menu菜单
- 1.2 准备菜单数据
- 1.3 循环渲染菜单
- 1.3.1 el-menu结构
- 1.3.2 动态渲染图标
- 1.4 样式设计
- 1.5 整体代码(CommonAside.vue)
- 2 CommonHeader组件(静态搭建)
- 2.1 准备图片URL数据
- 2.2 页面布局
- 2.3 样式设计
- 2.4 整体代码(CommonHeader.vue)
- 3 附录
- 3.1 列表filter
- 3.2 参考附录
左侧菜单栏:el-menu构建菜单,通过component渲染图标。头部导航栏:左侧是一个图标,中间是面包屑,右侧是dropdown。
1 CommonAside组件(静态搭建)
1.1 Menu菜单
从element-ui中将Menu菜单的代码拷贝过来,如下所示:
1.2 准备菜单数据
对其进行循环操作,提前准备一份数据,如下所示:
(1)path: 路由路径(URL地址)。
(2)name: 路由名称,用于编程式导航或RouterLink。
(3)label: 菜单上显示的名称。
(4)icon: 显示的图标(可能使用如 Element Plus, Font Awesome 等图标库)。
(5)url: 可能指向对应的组件文件名或组件名称。
使用了Vue 3的computed(计算属性)来对一个菜单或树形结构的列表list进行分类,分别筛选出:
(1)没有子项的项(叶子节点)。
(2)有子项的项(非叶子节点,通常用于展开的菜单组)。
1.3 循环渲染菜单
图标+标签
1.3.1 el-menu结构
<el-menu-item>菜单项</el-menu-item>
<el-sub-menu index="group"><template #title>主标题</template><el-menu-item-group title="分组标题"><el-menu-item index="1">选项1</el-menu-item><el-menu-item index="2">选项2</el-menu-item></el-menu-item-group>
</el-sub-menu>
el-menu-item-group通常嵌套在el-sub-menu或直接放在el-menu内。
1.3.2 动态渲染图标
需要确保:图标组件已注册(全局或局部)。
<component :is="item.icon" class="icons" />
(1)component:是Vue内置的“元组件”,用于动态渲染不同的组件。
(2):is=“item.icon”:绑定is属性,告诉Vue要渲染哪一个组件。
item.icon应该是一个组件的名称或组件本身的引用。
(3)class=“icons”:无论渲染哪个组件,都会加上icons这个CSS类。
1.4 样式设计
1.5 整体代码(CommonAside.vue)
<template><el-aside width="180px"><el-menu background-color="#545c64"><h3>通用后台管理系统</h3><el-menu-item v-for="item in noChildren" :index="item.path" :key="item.path"><component class="icons" :is="item.icon"></component><span>{{ item.label }}</span></el-menu-item><el-sub-menu v-for="item in hasChildren" :index="item.path" :key="item.path"><template #title><component class="icons" :is="item.icon"></component><span>{{ item.label }}</span></template><el-menu-item-group><el-menu-item v-for="(subItem,subIndex) in item.children" :index="subItem.path" :key="subItem.path"><component class="icons" :is="subItem.icon"></component><span>{{ subItem.label }}</span></el-menu-item></el-menu-item-group></el-sub-menu></el-menu></el-aside>
</template >
<script setup>import {ref,computed} from 'vue'import { useRouter } from 'vue-router';const router = useRouter()const list = ref([{path:"/home",name:"home",label:"首页",icon:"house",url:"Home"},{path:"/mail",name:"mail",label:"商品管理",icon:"video-play",url:"Mail"},{path:"/user",name:"user",label:"用户管理",icon:"user",url:"User"},{path:"other",label:"其他",icon:"location",children:[{path:"/page1",name:"page1",label:"页面1",icon:"setting",url:"Page1"},{path:"/page2",name:"page2",label:"页面2",icon:"setting",url:"Page2"}]}])const noChildren = computed(()=>list.value.filter(item=>!item.children))const hasChildren = computed(()=>list.value.filter(item=>item.children))
</script>
<style lang="less" scoped> .icons{width: 18px;height: 18px;margin-right: 5px;}.el-menu{border: none;h3{line-height: 48px;color: #333;text-align:center;}}.el-aside{ height: 100%;background-color: #545C64;}
</style>
2 CommonHeader组件(静态搭建)
左中右三部分:左侧是一个图标,中间是面包屑,右侧是dropdown。
2.1 准备图片URL数据
Vue 3 + Vite项目中动态引入本地静态资源(如图片)的推荐方式。
根据传入的user名称(如 ‘avatar’),动态生成指向src/assets/img/avatar.png的绝对路径URL,确保图片能在生产环境中正确加载。
<script setup>const getImageUrl= (user) => { return new URL(`../assets/img/${user}.png`,import.meta.url).href}
</script>
(1)import.meta.url: 这是一个特殊的元属性,它返回当前模块文件(即这个.vue文件)的完整URL。
Vite(Vue常用的构建工具)利用这个信息来计算第一个参数中相对路径的绝对位置。
(2).href: new URL()返回一个URL对象,.href属性获取该对象的完整字符串形式的URL。
这个URL是经过Vite构建系统处理过的,确保在开发和生产环境中都能正确访问资源(例如,生产环境可能包含哈希值)。
2.2 页面布局
按钮、面包屑、下拉菜单。
2.3 样式设计
(1)display: flex; 启用Flex布局,让子元素可以灵活排列。
(2)justify-content: space-between; 主轴方向两端对齐,第一个子元素靠左,最后一个靠右,中间自动留白。
(3)align-items: center; 交叉轴居中对齐,所有子元素在垂直方向居中。
(4)width: 100%; height: 100%; 占满父容器的宽高(常用于el-header或类似容器)。
(5)background-color: #333; 深灰色背景,常用于导航栏。
(1):deep(…):Vue提供的深度选择器(deep selector),用于在scoped样式中穿透到子组件的内部DOM。
(2).bread span:选择所有拥有class="bread"的元素内部的span。
(3)color: #fff !important; cursor: pointer !important;:
强制将文字颜色设为白色。
鼠标悬停时显示为手型指针(可点击提示)。
2.4 整体代码(CommonHeader.vue)
<template><div class="header"><div class="l-content"><el-button size="small"><component class="icons" is="menu"></component></el-button><el-breadcrumb separator="/" class="bread"><el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item></el-breadcrumb></div><div class="r-content"><el-dropdown><span class="el-dropdown-link"><img :src="getImageUrl('user')" class="user"/></span><template #dropdown><el-dropdown-menu><el-dropdown-item>个人中心</el-dropdown-item><el-dropdown-item>退出</el-dropdown-item></el-dropdown-menu></template></el-dropdown></div></div>
</template><script setup>const getImageUrl= (user) => { return new URL(`../assets/img/${user}.png`,import.meta.url).href}
</script><style lang="less" scoped> .header{ display: flex;justify-content: space-between;align-items: center;width: 100%;height: 100%;background-color: #333;}.icons{width: 20px;height: 20px;}.l-content{display: flex;align-items: center;.el-button{margin-right: 20px;}}.r-content{.user{width: 40px;height: 40px;border-radius: 50%;}}:deep(.bread span){color:#fff !important;cursor: pointer !important;}
</style>
3 附录
3.1 列表filter
const list = [1,2,3];
const a = list.filter(item => item != 1);
alert(a);
返回2、3。
3.2 参考附录
参考elementplus官网地址
参考vue3实现通用后台管理(傻瓜式一步一步记录代码实现过程)
参考js代码在线运行工具