vue3项目实战(六)--右侧头部组件实现(导航菜单伸缩、静态面包屑)

本文详细介绍了如何在Vue项目中使用ElementPlus构建头部组件,包括el-header的配置、布局页面导入、pinia状态管理、菜单的伸缩控制以及路由的懒加载和错误处理。
摘要由CSDN通过智能技术生成

一、头部组件实现

1.1 在layout目录下新建appHeader目录、并在目录下新建AppHeader组件。直接去element plus官网找 对应的静态源码即可

<template>
  <el-header class="layout-header">
    <!--    图标-->
    <el-icon>
      <expand v-show="!isCollapse" @click="handleClose()"/>
      <fold v-show="isCollapse" @click="handleOpen()"/>
    </el-icon>
    <!--    面包屑-->
    <el-breadcrumb separator="/">
      <el-breadcrumb-item>homepage</el-breadcrumb-item>
      <el-breadcrumb-item
        ><a href="/">promotion management</a></el-breadcrumb-item
      >
      <el-breadcrumb-item>promotion list</el-breadcrumb-item>
      <el-breadcrumb-item>promotion detail</el-breadcrumb-item>
    </el-breadcrumb>

    <!--    下拉菜单-->
    <el-dropdown>
      <span class="el-dropdown-link">
        <el-avatar :size="32" :src="'https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png'"></el-avatar>
        <el-icon class="el-icon--right">
          <arrow-down></arrow-down>
        </el-icon>
      </span>
      <template #dropdown>
        <el-dropdown-menu>
          <el-dropdown-item>用户姓名</el-dropdown-item>
          <el-dropdown-item disabled>退出</el-dropdown-item>
        </el-dropdown-menu>
      </template>
    </el-dropdown>
  </el-header>
</template>
<script setup lang="ts">
import { reactive, computed } from 'vue'
import { ArrowDown, Expand, Fold } from '@element-plus/icons-vue'
import { mainStore } from '@/store'


const ms = mainStore()
const isCollapse = computed(() => {
  return ms.getCollapse
})

const handleClose = ()=>{
  console.log("handleClose"+isCollapse.value)
  if(!isCollapse.value){
    ms.setCollapse(!isCollapse.value)
  }

}
const handleOpen = ()=>{
  console.log("handleOpen"+isCollapse.value)
  if(isCollapse.value){
    ms.setCollapse(!isCollapse.value)
  }
}
</script>

<style lang="scss" scoped>
.layout-header {
  height: $base-tabbar-height;
  background-color: palegoldenrod;
  display: flex;
  align-items: center;

  .el-dropdown{
    margin-left: auto;
    .el-dropdown-link{
      display: flex;
      align-items: center;
      justify-content: center;
    }
  }
  .el-icon{
    margin-right:17px;
  }
}
</style>

1.2 布局页面导入AppHeader

引入 app-header组件 并对之前的右侧路由视图添加滚动组件
在这里插入图片描述

1.3 使用pinia来控制多个伸缩状态

安装pinia组件 在src下新建store目录,目录下新建index.ts

import { defineStore } from 'pinia'

export const mainStore = defineStore('mainStore', {
  state() {
    return {
      // 定义一个是否水平折叠收起菜单 默认值是false。 true表示菜单折叠
      isCollapse: false
    }
  },
  getters: {
    getCollapse: state => state.isCollapse
  },
  actions: {
    setCollapse(isCollapse: boolean) {
      this.isCollapse = isCollapse
    }
  }
})

1.4 main.ts使用pinia

在这里插入图片描述

1.5 导航菜单页面伸缩

<template>
  <el-aside class="layout-menu" :width="!isCollapse ? '260px' : '64px'">
    <!-- logo -->
    <div class="layout-logo" v-show="!isCollapse">
      <img src="@/assets/vue.svg" alt="logo图标" />
      <p>v3后台管理系统</p>
    </div>
    <!-- 展示菜单 -->
    <!-- 滚动组件 -->
    <el-scrollbar class="layout-scrollbar">
      <!-- 菜单组件-->
      <el-menu
        active-text-color="#ffd04b"
        background-color="#545c64"
        class="el-menu-vertical-demo"
        default-active="2"
        text-color="#fff"
        router
        :collapse="isCollapse"
      >
        <!-- 菜单列表组件即菜单树-->
        <MenuTree :menu-list="menuItems"></MenuTree>
      </el-menu>
    </el-scrollbar>
  </el-aside>
</template>
<script setup lang="ts">
import { reactive, computed } from 'vue'
import { mainStore } from '@/store/index.ts'
import MenuTree from '@/components/MenuTree/MenuTree.vue'
import Dict from '@/views/system/dict/Dict.vue'
import Acl from '@/views/acl/Acl.vue'
import Role from '@/views/acl/role/Role.vue'
import Permission from '@/views/acl/permission/Permission.vue'
import AclUser from '@/views/acl/user/AclUser.vue'
const ms = mainStore()
const isCollapse = computed(() => {
  return ms.getCollapse
})
const menuItems = reactive([
  {
    name: 'index',
    path: '/index',
    meta: {
      title: '首页',
      hidden: false,
      icon: 'HomeFilled'
    }
  },
  {
    name: 'Acl',
    path: '/acl',
    meta: {
      title: '权限管理',
      icon: 'Lock'
    },
    redirect: '/acl/user',
    children: [
      {
        name: 'User',
        path: '/acl/user',
        component: AclUser,
        meta: {
          title: '用户管理',
          icon: 'User'
        }
      },
      {
        path: '/acl/role',
        component: Role,
        name: 'Role',
        meta: {
          title: '角色管理',
          icon: 'UserFilled'
        }
      },
      {
        path: '/acl/permission',
        component: Permission,
        name: 'Permission',
        meta: {
          title: '菜单管理',
          icon: 'Monitor'
        }
      }
    ]
  },

  {
    name: 'system',
    path: '/system',
    meta: {
      title: '系统管理',
      icon: 'Setting'
    },
    children: [
      {
        path: '/system/dict',
        component: Dict,
        name: 'Permission',
        meta: {
          title: '字典管理',
          icon: 'Monitor',
          hidden: false
        }
      }
    ]
  }
])

</script>

<style lang="scss" scoped>
.layout-menu {
  border-right: 1px solid #e4e7ed;
  background-color: $base-menu-background;
  .layout-logo {
    width: 100%;
    height: $base-menu-logo-height;
    color: white;
    display: flex;
    align-items: center;
    img {
      width: 40px;
      height: 40px;
    }
    p {
      color: white;
    }
  }

  .layout-scrollbar {
    width: 100%;
    height: calc(100vh - $base-menu-logo-height);
    .el-menu {
      border-right: none;
      background-color: $base-menu-background;
    }
    .el-menu-vertical-demo:not(.el-menu-c--collapse) {
      width: $base-menu-width;
    }
  }
}
</style>

在这里插入图片描述

1.6 优化roueter文件夹下的index.ts

页面组件才有懒加载方式,同时增加错误页面

import {
createRouter,
createWebHashHistory,
type RouteRecordRaw
} from ‘vue-router’
// 引入 login.ts
import LoginRouter from ‘@/router/modules/login.ts’
// RouteRecordRaw 内置的接口类型
const routes: RouteRecordRaw[] = [
…LoginRouter,
{
path: ‘/’,
redirect: ‘/layout’
},

{
path: ‘/layout’, // 布局页
name: ‘LayOut’,
component: ()=> import(‘@/views/layout/LayOut.vue’),
redirect: ‘/index’, // 进入主页的时候重定向到Index页面
children: [
{ path: ‘/:pathMatch(.)’,
name: ‘NotFound’,
component: ()=> import(‘@/views/error/Error.vue’)
},
{
path: ‘/index’,
name: ‘index’,
component: ()=> import(‘@/views/layout/index/Index.vue’)
},
{
path: ‘/acl’,
name: ‘Acl’,
component: ()=> import(‘@/views/error/Error.vue’),
children: [
{
path: ‘/acl/user’,
name: ‘User’,
component: ()=> import(‘@/views/acl/user/AclUser.vue’) ,

      },
      {
        path: '/acl/role',
        name: 'Role',
        component: ()=> import('@/views/acl/role/Role.vue')
      },
      {
        path: '/acl/permission',
        name: 'Permission',
        component: ()=> import('@/views/acl/permission/Permission.vue') ,
      }
    ]
  },
  {
    path: '/system',
    name: 'system',
    component: ()=> import('@/views/system/System.vue'),
    children: [
      {
        path: '/system/dict',
        name: 'dict',
        component:  ()=> import('@/views/system/dict/Dict.vue')
      }
    ]
  }
]

}
]

const router = createRouter({
history: createWebHashHistory(),
routes
})

// 导出路由
export default router

1.7 启动项目运行效果

在这里插入图片描述在这里插入图片描述

  • 40
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值