Vue--》Vue3打造可扩展的项目管理系统后台的完整指南(三)

今天开始使用 vue3 + ts 搭建一个项目管理的后台,因为文章会将项目的每一个地方代码的书写都会讲解到,所以本项目会分成好几篇文章进行讲解,我会在最后一篇文章中会将项目代码开源到我的GithHub上,大家可以自行去进行下载运行,希望本文章对有帮助的朋友们能多多关注本专栏,学习更多前端vue知识,然后开篇先简单介绍一下本项目用到的技术栈都有哪几个方面(阅读本文章能够学习到的技术):

vite:快速轻量且功能丰富的前端构建工具,帮助开发人员更高效构建现代Web应用程序。

pnpm:高性能、轻量级npm替代品,帮助开发人员更加高效地处理应用程序的依赖关系。

Vue3:Vue.js最新版本的用于构建用户界面的渐进式JavaScript框架。

TypeScript:JavaScript的超集,提供了静态类型检查,使得代码更加健壮。

Animate:基于JavaScript的动画框架,它使开发者可以轻松创建各种炫酷的动画效果。

vue-router:Vue.js官方提供的路由管理器与Vue.js紧密耦合,非常方便与Vue.js一同使用。

Pinia:Vue3构建的Vuex替代品,具有响应式能力,提供非常简单的 API,进行状态管理。

element-plus:基于Vue.js 3.0的UI组件库,用于构建高品质的响应式Web应用程序。

axios:基于Promise的HTTP客户端,可以在浏览器和node.js中使用。

扫描二维码关注公众号,回复: 15165869 查看本文章

three:基于JavaScript的WebGL库,开发者可以编写高性能、高质量的3D场景呈现效果。

echarts:基于JavaScript的可视化图表库,支持多种类型的图表,可根据需要自行安装。

当然还有许多其他的需要安装的第三方库,这里就不再一一介绍了,在项目中用到的地方自行会进行讲解,大家自行学习即可,现在就让我们走进vue3+ts的实战项目吧。

目录

后台页面布局

左侧菜单栏布局

自定义导航菜单

顶部tabbar静态页面的搭建

菜单折叠效果


后台页面布局

今天我们采用 “经典三栏布局” ,它是一种常见的网页布局方式,通常在后台管理系统、企业门户网站等需要大量展示信息的网站中使用。左侧菜单栏用于导航界面,右侧上部可以用来展示头部信息和搜索框,而正文内容通常放在右侧中部,底部则放置一些网站相关的信息和链接。

三列式布局的优点是布局清晰,易于维护和扩展,同时也能够适应不同屏幕分辨率和设备类型的需求。在移动设备上,可以通过响应式设计等技术手段将其转化为单列布局或者其他适应屏幕的布局方式。今天就以手写方式进行该布局的实现:

首先我们先定义好三栏布局的html结构:

<template>
  <div class="layout">
    <!-- 左侧菜单 -->
    <div class="layout_slider">12</div>
    <div class="layout_tabbar">213</div>
    <div class="layout_main"></div>
    <div class="layout_fonter"></div>
  </div>
</template>

因为三栏布局项目中可能会有一些地方都用到到,这里我将一些三栏布局的变量封装成全局变量,当然我们这个项目是没有这种场景的,但是大项目中这样做可能会有一些奇效,这里提前做好:

第一篇文章 :已经讲解了如何封装全局CSS样式,忘记了的朋友可以回头翻翻看看,这里我在我定义好的全局scss样式表variable.scss文件中定义如下全局变量:

// 项目提供scss全局变量

// 左侧的菜单宽度
$base-menu-width: 260px;
// 左侧菜单的背景颜色
$base-menu-background: #4682B4;
// 顶部导航的高度
$base-tabbar-height: 60px;

接下来就是引用这些定义好的变量,然后通过计算宽度高度值来得到准确的布局样式,如下:

<style lang="scss" scoped>
.layout {
  width: 100%;
  height: 100vh;
  background: red;
  .layout_slider {
    width: $base-menu-width;
    height: 100vh;
    background: $base-menu-background;
  }
  .layout_tabbar {
    position: fixed;
    width: calc(100% - $base-menu-width);
    height: $base-tabbar-height;
    background: cyan;
    top: 0px;
    left: $base-menu-width;
  }
  .layout_main {
    position: absolute;
    width: calc(100% - $base-menu-width);
    height: calc(100vh - $base-tabbar-height * 2);
    background: #0f0;
    left: $base-menu-width;
    top: $base-tabbar-height;
    box-sizing: border-box;
    padding: 20px;
    overflow: auto;
  }
  .layout_fonter {
    position: fixed;
    width: calc(100% - $base-menu-width);
    height: $base-tabbar-height;
    background: cyan;
    bottom: 0;
    left: $base-menu-width;
  }
}
</style>

当然我们也可以在全局样式 index.scss 文件中定义我们想要的滚动条的效果(按照自己喜欢配置):

// 设置滚动条的样式
::-webkit-scrollbar{
  width: 5px;
}
::-webkit-scrollbar-track {
  background: white;
}
::-webkit-scrollbar-thumb {
  width: 8px;
  background-color: rgb(16, 20, 16);
  border-radius: 10px;
}

为了方便查看效果,我们给layout_main主体中添加一些高度让效果更加明显一点:

左侧菜单栏布局

左侧菜单栏是一种常见的前端界面元素,通常被用作网站或应用的导航和功能入口。它通常出现在页面的左侧,展示了一系列链接或按钮,用户可以通过点击这些链接或按钮实现页面间的切换或功能的开启。接下来将实现左侧菜单栏样式功能的书写:

logo样式设置:左侧菜单栏logo的话,这里我单独抽离出一个组件进行设置,在抽离出组件的同时这里我将存放logo图片和文字资源进行放置在一个单独的ts文件中,方便用户的修改:

import img from '../assets/images/logo1.jpg'
// 用于项目logo|标题配置
export default {
  title: '商品运营管理平台',
  logo: img,
  logoHidden: true, // logo组件是否隐藏设置
}

然后将该文件在logo组件中进行引入,然后配置一下相关样式,具体代码如下:

<template>
  <div class="logo" v-if="settings.logoHidden">
    <img :src="settings.logo" alt="logo图片" />
    <p>{
   
   { settings.title }}</p>
  </div>
</template>

<script setup lang="ts">
// 引入设置logo与标题的配置文件
import settings from '@/utils/settings'
</script>

<style lang="scss" scoped>
.logo {
  width: 100%;
  height: $base-menu-logo-height;
  color: white;
  display: flex;
  align-items: center;
  box-sizing: border-box;
  padding: 10px;
  img {
    width: 40px;
    height: 40px;
  }
  p {
    font-size: $base-logo-title-fontSize;
    margin-left: 10px;
  }
}
</style>

菜单栏样式设置: 左侧菜单栏选项,这里的话我采用element-plus给我们提供的一些组件进行使用

首先我们先对左侧菜单栏的内容布局样式进行设置,这里采用element的滚动条样式进行设置:

计算滚动条的高度:

自定义导航菜单

这里通过自定义导航菜单的方式,不管导航菜单有多少,根据自己路由表配置的数量的多少而显示,相关步骤如下:

在Pinia仓库中进行存储生成菜单需要的数组(路由)

这里当导航菜单抽离出一个组件:

在导航组件中书写如下样式:

<template>
  <template v-for="item in menuList" :key="item.path">
    <!-- 没有子路由 -->
    <template v-if="!item.children">
      <el-menu-item
        v-if="!item.meta.hidden"
        :index="item.path"
        @click="goRoute"
      >
        <template #title>
          <el-icon>
            <component :is="item.meta.icon"></component>
          </el-icon>
          <span>{
   
   { item.meta.title }}</span>
        </template>
      </el-menu-item>
    </template>
    <!-- 只有一个子路由 -->
    <template v-if="item.children && item.children.length == 1">
      <el-menu-item
        v-if="!item.children[0].meta.hidden"
        :index="item.children[0].path"
        @click="goRoute"
      >
        <template #title>
          <el-icon>
            <component :is="item.children[0].meta.icon"></component>
          </el-icon>
          <span>{
   
   { item.children[0].meta.title }}</span>
        </template>
      </el-menu-item>
    </template>
    <!-- 有超过1个的子路由 -->
    <el-sub-menu
      :index="item.path"
      v-if="item.children && item.children.length > 1"
    >
      <template #title>
        <el-icon>
          <component :is="item.meta.icon"></component>
        </el-icon>
        <span>{
   
   { item.meta.title }}</span>
      </template>
      <Menu :menuList="item.children"></Menu>
    </el-sub-menu>
  </template>
</template>

<script setup lang="ts">
import { useRouter } from 'vue-router'
// 获取父组件传递过来的全部路由数组
defineProps(['menuList'])
// 获取路由器对象
let $router = useRouter()
// 点击菜单的回调
const goRoute = (vc: any) => {
  $router.push(vc.index)
}
</script>
<script lang="ts">
export default {
  // eslint-disable-next-line vue/no-reserved-component-names
  name: 'Menu',
}
</script>
<style lang="scss" scoped></style>

然后我们在将路由出口位置也封装成一个组件:

在路由出口文件编写过渡动画增添点页面效果:

<template>
  <!-- 路由组件出口位置 -->
  <router-view v-slot="{ Component }">
    <transition name="fade">
      <!-- 渲染home主页下的一级路由组件下的子路由 -->
      <component :is="Component"></component>
    </transition>
  </router-view>
</template>
<script setup lang="ts"></script>
<style lang="scss" scoped>
.fade-enter-from {
  opacity: 0;
  transform: scale(0);
}
.fade-enter-active {
  transition: all 0.3s;
}
.fade-enter-leave {
  opacity: 1;
  transform: scale(1);
}
</style>

具体的结果如下:

这里有一个问题就是,当你点击某个菜单之后刷新页面,默认情况下所有的折叠菜单都会关闭的,如果你想在点击折叠菜单中的子菜单之后刷新页面当前选择的折叠菜单不进行折叠,可以通过如下方式实现:

顶部tabbar静态页面的搭建

在后台管理页面中,顶部 TabBar 组件的作用通常是帮助管理员快速切换不同的功能模块,方便管理各种信息和数据。后台管理页面通常包含了大量的功能模块和数据展示页面,例如用户管理、文章管理、订单管理等,这些页面之间可能存在复杂的关联和交互,因此需要一个能够方便、快速地进行页面切换的工具。

顶部tabbar组件我抽离出两部分,分别放置在顶部的两侧,如下:

<template>
  <div class="tabbar">
    <div class="tabbar_left">
      <Breadcrumb></Breadcrumb>
    </div>
    <div class="tabbar_right">
      <Setting></Setting>
    </div>
  </div>
</template>

<script setup lang="ts">
import Breadcrumb from './breadcrumb/index.vue'
import Setting from './seting/index.vue'
</script>

采用flex布局进行设置让其分布在顶部的两端:

<style lang="scss" scoped>
.tabbar {
  width: 100%;
  height: 100%;
  display: flex;
  justify-content: space-between;
  background-image: linear-gradient(
    to right,
    rgb(210, 179, 179),
    rgb(218, 202, 202),
    rgb(227, 206, 206)
  );
  align-items: center;
  .tabbar_left {
    display: flex;
    margin-left: 20px;
  }
  .tabbar_right {
    display: flex;
    align-items: center;
  }
}
</style>

在顶部的左侧我设置一个面包屑样式:

<template>
  <!-- 左侧的静态 -->
  <el-icon style="margin-right: 10px">
    <Expand></Expand>
  </el-icon>
  <!-- 左侧面包屑 -->
  <el-breadcrumb separator-icon="ArrowRight">
    <el-breadcrumb-item>权限管理</el-breadcrumb-item>
    <el-breadcrumb-item>用户管理</el-breadcrumb-item>
  </el-breadcrumb>
</template>

<script setup lang="ts"></script>

<style lang="scss" scoped></style>

在顶部的右侧我设置element的按钮和下拉菜单:

<template>
  <el-button type="primary" size="small" icon="Refresh" circle></el-button>
  <el-button type="primary" size="small" icon="FullScreen" circle></el-button>
  <el-button type="primary" size="small" icon="Setting" circle></el-button>
  <img
    src="@/assets/images/bg4.jpg"
    style="width: 24px; height: 24px; border-radius: 50%; margin: 0 10px"
  />
  <!-- 下拉菜单 -->
  <el-dropdown>
    <span class="el-dropdown-link">
      admin
      <el-icon class="el-icon--right">
        <arrow-down />
      </el-icon>
    </span>
    <template #dropdown>
      <el-dropdown-menu>
        <el-dropdown-item>退出登录</el-dropdown-item>
      </el-dropdown-menu>
    </template>
  </el-dropdown>
</template>

<script setup lang="ts"></script>

<style lang="scss" scoped></style>

最后的结果如下:

菜单折叠效果

在element-plus中已经给出了折叠面板的案例,接下来我将手写实现其案例:

在pinia仓库中定义一个布尔函数用于判断折叠面板的折叠与展开:

// 关于导航组件相关的仓库
import { defineStore } from 'pinia'

const useLayOutSettingStore = defineStore('SettingStore', {
  state: () => {
    return {
      fold: false, // 用户控制菜单折叠还是收起的控制
    }
  },
})

export default useLayOutSettingStore

给折叠面板的按钮添加点击事件来动态的切换面板样式:

<template>
  <!-- 左侧的静态 -->
  <el-icon style="margin-right: 10px" @click="changeIcon">
    <component :is="LayOutSettingStore.fold ? 'Fold' : 'Expand'"></component>
  </el-icon>
  <!-- 左侧面包屑 -->
  <el-breadcrumb separator-icon="ArrowRight">
    <el-breadcrumb-item>权限管理</el-breadcrumb-item>
    <el-breadcrumb-item>用户管理</el-breadcrumb-item>
  </el-breadcrumb>
</template>

<script setup lang="ts">
import useLayOutSettingStore from '@/store/settings'
// 获取仓库中layout相关配置的信息
let LayOutSettingStore = useLayOutSettingStore()

const changeIcon = () => {
  LayOutSettingStore.fold = !LayOutSettingStore.fold
}
</script>

<style lang="scss" scoped></style>

改变状态值和面板样式之后,接下来给Menu设置可以折叠的属性:

本项目的导航页面功能的搭建就讲解到这,下一篇文章将讲解顶部tabber功能搭建和main主体内容,关注博主学习更多前端vue知识,您的支持就是博主创作的最大动力! 

猜你喜欢

转载自blog.csdn.net/qq_53123067/article/details/130958538