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

news2024/11/25 17:51:21

今天开始使用 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中使用。

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

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

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

目录

品牌管理模块静态搭建

品牌管理数据展示

分页器点击相关操作

对话框静态搭建

实现添加修改删除业务的功能

表单自定义规则校验


品牌管理模块静态搭建

品牌管理模块的静态搭建这里需要使用element-plus组件库提供的相关标签实现快速搭建样式,我们采用卡片样式,最外层用el-card进行包裹:

<template>
  <el-card class="box-card">
  </el-card>
</template>

卡片里面的样式就可以根据自己的喜好随意搭配了,这里我存放了一个按钮、表格和分页器:

<el-card class="box-card">
  <!-- 卡片顶部添加按钮 -->
  <el-button type="primary" size="default" icon="Plus">添加品牌</el-button>
  <!-- 表格组件,用于展示已有的平台数据 -->
  <el-table style="margin: 10px 0px" border>
    <el-table-column
      label="序号"
      width="80px"
      align="center"
    ></el-table-column>
    <el-table-column label="品牌名称"></el-table-column>
    <el-table-column label="品牌Logo"></el-table-column>
    <el-table-column label="品牌操作"></el-table-column>
  </el-table>
  <!-- 分页器组件 -->
  <el-pagination
    v-model:current-page="pageNo"
    v-model:page-size="limit"
    :page-sizes="[3, 5, 7, 9]"
    background="true"
    layout="prev, pager, next, jumper, ->, sizes, total"
    :total="400"
  />
</el-card>

通过JS定义相关变量实现响应式数据:

<script setup lang="ts">
import { ref } from 'vue'
// 当前的页码
let pageNo = ref<number>(1)
// 每页展示多少条数据
let limit = ref<number>(3)
</script>

最后实现的静态页面效果如下所示:

品牌管理数据展示

在显示内容方面,我们可用借助Table组件库中的prop属性进行展示内容

对应的数据就会展示出来:

使用prop默认是以div包裹进行展示的,当然这里也可以使用template插槽进行展示数据,接下来的图片和操作都可以使用插槽来完成:

分页器点击相关操作

接下来开始对点击分页器进行相关数据切换操作,这里我们采用的是组件库中的分页器给我们提供的相关API进行操作:

我们在点击分页按钮后,其API会自动将相关的页数进行一个注入,所以我们不需要进行传递参数来实现:

因为是自动注入相关的页码值数据,所以我们也可以直接调用获取数据的方法,不需要再额外定义一个新的函数,定义分页数也可以采用相同的方法,不过为了让在点击分页数之后,页码值会跳转到第一页,可以传递一个默认参数,如果没有传递参数的话,默认就是1,传递的话就会覆盖默认值:

对话框静态搭建

在项目中添加品牌和修改品牌的相关数据都需要借助对话框来实现,所以这里就需要简单的搭建一下对话框并使用,如下借助组件库使用:

<!-- 对话框组件:在添加品牌和修改已有品牌的业务时侯使用该结构 -->
<el-dialog v-model="dialogFormVisible" title="添加品牌">
  <el-form style="width: 80%">
    <el-form-item label="品牌名称" label-width="80px">
      <el-input placeholder="请您输入品牌名称"></el-input>
    </el-form-item>
    <el-form-item label="品牌LOGO" label-width="80px">
      <el-upload
        class="avatar-uploader"
        action="https://run.mocky.io/v3/9d059bf9-4660-45f2-925d-ce80ad6c4d15"
        :show-file-list="false"
        :on-success="handleAvatarSuccess"
        :before-upload="beforeAvatarUpload"
      >
        <img v-if="imageUrl" :src="imageUrl" class="avatar" />
        <el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon>
      </el-upload>
    </el-form-item>
  </el-form>
  <!-- 具名插槽:设置相关按钮 -->
  <template #footer>
    <el-button type="primary" size="default" @click="cancel">
      取消
    </el-button>
    <el-button type="primary" size="default" @click="confirm">
      确定
    </el-button>
  </template>
</el-dialog>

当然我们要为添加品牌和修改品牌的按钮设置点击事件来更改

// 添加品牌按钮的回调
const addTrademark = () => {
  // 对话框显示
  dialogFormVisible.value = true
}
// 修改已有品牌数据的回调
const updateTrademark = () => {
  // 对话框显示
  dialogFormVisible.value = true
}
// 对话框底部取消按钮
const cancel = () => {
  // 对话框隐藏
  dialogFormVisible.value = false
}
// 对话框底部确定按钮
const confirm = () => {
  // 对话框隐藏
  dialogFormVisible.value = false
}

最后呈现的结果如下:

接下来给上传图片设置相关的格式校验:

// 上传图片组件,钩子是在图片上传成功之前触发,上传文件之前可以约束文件类型与大小
const beforeAvatarUpload: UploadProps['beforeUpload'] = (rawFile) => {
  if (
    rawFile.type == 'image/png' ||
    rawFile.type == 'image/jpg' ||
    rawFile.type == 'image/gif' ||
    rawFile.type == 'image/jpeg'
  ) {
    if (rawFile.size / 1024 / 1024 < 4) {
      return true
    } else {
      ElMessage({
        type: 'error',
        message: '上传文件大小应小于4M',
      })
    }
  } else {
    ElMessage({
      type: 'error',
      message: '上传文件格式务必PNG|JPG|GIF|JPEG',
    })
    return false
  }
}
// 图片上传成功的钩子
const handleAvatarSuccess: UploadProps['onSuccess'] = (response) => {
  // 收集图片的地址
  trademarkParams.logoUrl = response.data
}

实现添加修改删除业务的功能

接下来实现数据的增删改操作,当然这里的话也是要和后端搭配借助相关的接口实现,如下:

// 书写品牌管理模块的接口
import request from '@/utils/request'
// 引入ts类型
import type { TradeMarkResponseData, TradeMark } from './type'
// 品牌管理模块接口地址
enum API {
  // 获取已有品牌接口
  TRADEMAKE_URL = '/admin/product/baseTrademark/',
  // 添加品牌
  ADDTRADEMAKE_URL = '/admin/product/baseTrademark/save',
  // 修改品牌
  UPDATETRADEMAKE_URL = '/admin/product/baseTrademark/update',
  // 删除已有品牌数据
  DELETE_URL = '/admin/product/baseTrademark/remove/',
}
// 获取已有品牌的接口方法:page:获取第几页;limit:获取几个已有品牌的数据
export const reqHasTrademark = (page: number, limit: number) =>
  request.get<any, TradeMarkResponseData>(API.TRADEMAKE_URL + `${page}/${limit}`)
// 添加和修改已有品牌接口方法
export const reqAddOrUpdateTrademark = (data: TradeMark) => {
  // 修改已有品牌的数据
  if (data.id) {
    return request.put<any, any>(API.UPDATETRADEMAKE_URL, data)
  } else {
    // 新增品牌数据
    return request.post<any, any>(API.ADDTRADEMAKE_URL, data)
  }
}
// 删除某一个已有品牌的数据
export const reqDeleteTrademark = (id: number) => request.delete<any, any>(API.DELETE_URL + id)

在点击对话框的确定按钮后调用添加数据业务,因为添加数据是不需要id的,后端会自动帮助我们生成相应的id,但是修改业务需要借助相应id,所以这里我们通过id的与否来判断是我们是选择添加品牌还是修改品牌:

// 对话框底部确定按钮
const confirm = async () => {
  let result: any = await reqAddOrUpdateTrademark(trademarkParams)
  // 添加品牌成功
  if (result.code == 200) {
    // 对话框隐藏
    dialogFormVisible.value = false
    // 弹出提示信息
    ElMessage({
      type: 'success',
      message: trademarkParams.id ? '修改品牌成功' : '添加品牌成功',
    })
    // 再次发请求获取已有全部的品牌数据
    hasTrademark(trademarkParams.id ? pageNo.value : 1)
  } else {
    // 添加品牌失败
    ElMessage({
      type: 'error',
      message: trademarkParams.id ? '修改品牌失败' : '添加品牌失败',
    })
  }
}

当我们点击修改按钮后,通过点击事件会自动获取当前修改品牌的相关数据,因为修改数据是具有其ID的,所以这里我们通过ES6语法对trademarkParams进行一个合并:

// 修改已有品牌数据的回调
const updateTrademark = (row: TradeMark) => {
  // 对话框显示
  dialogFormVisible.value = true
  // // 展示已有品牌的数据
  // trademarkParams.id = row.id
  // trademarkParams.tmName = row.tmName
  // trademarkParams.logoUrl = row.logoUrl
  // 使用ES6合并语法
  Object.assign(trademarkParams, row)
}

删除数据的方式同样简单,这里借助组件库中的气泡提示框进行书写,通过相关事件confirm来对其数据进行一个删除:

// 删除按钮的回调
const removeTradeMark = async (id: number) => {
  // 点击确定按钮删除已有品牌请求
  let result = await reqDeleteTrademark(id)
  if (result.code == 200) {
    ElMessage({
      type: 'success',
      message: '删除品牌成功',
    })
    // 再次发请求获取已有全部的品牌数据
    hasTrademark(trademarkArr.value.length > 1 ? pageNo.value : pageNo.value - 1)
  } else {
    ElMessage({
      type: 'error',
      message: '删除品牌失败',
    })
  }
}

呈现的结果如下:

表单自定义规则校验

接下来仍然需要对对话框中的文字和图片区域进行相关校验,校验规则如下:

// 品牌自定义校验规则(文字)
const validatorTmName = (_rule: any, value: any, callback: any) => {
  if (value.trim().length >= 2) {
    callback()
  } else {
    // 校验未通过返回的错误信息
    callback(new Error('品牌名称位数必须大于等于俩位'))
  }
}
// 品牌自定义校验规则(图片)
const validatorLogoUrl = (_rule: any, value: any, callback: any) => {
  // 如果图片上传
  if (value) {
    callback()
  } else {
    callback(new Error('LOGO图片务必上传!'))
  }
}
// 设置表单校验规则对象
const rules = {
  tmName: [{ required: true, trigger: 'blur', validator: validatorTmName }],
  logoUrl: [{ required: true, trigger: 'change', validator: validatorLogoUrl }],
}

设置完校验规则之后,我们需要在点击按钮之后对整个表单进行校验,如果校验不通过需要提示,当然这里需要通过ref来获取form表单的数据进行验证:

验证完成之后,在点击确定或者重新打开表单时需要清除相关的表单验证规则,因为初始进行是没有进行表单验证的,所以我们要使用可选链操作符进行判断:

最终达到的效果如下:

本项目的品牌管理页面功能的搭建就讲解到这,下一篇文章将继续讲解其它模块的主体内容,关注博主学习更多前端vue知识,您的支持就是博主创作的最大动力! 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/647851.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

学生成绩管理系统(逻辑清楚-简单实用)

1、需求分析 1.1、需求分析概述 需求分析是我们在软件开发中的重要环节&#xff0c;是软件开发的第一步也是最基础的环节&#xff0c;这将决定我们所实现的目标以及系统的各个组成部分、各部分的任务职能、以及使用到的数据结构、各个部门之间的组成关系和数据流程&#xff0…

chatgpt赋能python:Python列表操作:如何使用Python将数据放入列表中

Python列表操作&#xff1a;如何使用Python将数据放入列表中 在Python中&#xff0c;列表是一种重要的数据结构&#xff0c;允许我们将多个项目存储在单个变量中。在本文中&#xff0c;我们将介绍如何将数据放入Python列表中。我们将讨论Python中的列表数据类型以及如何向列表…

chatgpt赋能python:Python中如何放大图片

Python中如何放大图片 简介 图片是网站优化中不可或缺的一部分&#xff0c;然而&#xff0c;当图片在网站中被缩小或拉伸时&#xff0c;会导致其模糊或失真。在这种情况下&#xff0c;可以使用Python中的一些库来放大图片&#xff0c;同时保持图像的清晰度和质量。在本篇文章…

JavaScript 进阶 - 第3天

文章目录 JavaScript 进阶 - 第3天1 编程思想1.1 面向过程1.2 面向对象&#xff08;oop&#xff09; 2 构造函数3 原型对象3.1 原型3.2 constructor 属性3.3 对象原型3.4 原型继承3.5 原型链&#xff08;面试高频&#xff09; JavaScript 进阶 - 第3天 了解构造函数原型对象的语…

C++友元函数friend使用的学习总结

C友元函数friend使用的学习总结 1. 友元函数简介1.1 使用友元函数的目的1.2 友元函数的三种实现方法 2.全局函数做友元3.类做友元4.成员函数做友元注意&#xff01; 1. 友元函数简介 1.1 使用友元函数的目的 允许一个函数或者类访问另一个类中的私有成员,使得两个类可以共享同…

HTML学习(一)

Web标准 主要包括&#xff1a;结构&#xff0c;外观&#xff0c;行为三个方面 HTML标签&#xff0c;把标签学会&#xff0c;这门语言就基本学会了 双标签的关系&#xff0c;并列关系和包含关系 每个标签起作用的位置 vscode自动生成的代码的解释 <!DOCTYPE>文档类型声…

【RabbitMQ教程】第八章 —— RabbitMQ - 幂等性、优先级、惰性

&#x1f4a7; 【 R a b b i t M Q 教程】第八章—— R a b b i t M Q − 幂等性、优先级、惰性 \color{#FF1493}{【RabbitMQ教程】第八章 —— RabbitMQ - 幂等性、优先级、惰性} 【RabbitMQ教程】第八章——RabbitMQ−幂等性、优先级、惰性&#x1f4a7; &#x1f…

chatgpt赋能python:Python调试技巧:如何使用断点运行程序

Python调试技巧&#xff1a;如何使用断点运行程序 在Python编程中&#xff0c;程序出现错误或需要调试时&#xff0c;我们需要一些工具来帮助我们定位问题和修复代码。其中之一就是使用断点来运行程序。接下来我们将讨论如何在Python中使用断点进行程序调试的相关技巧。 什么…

C++11核心特性---右值引用(代码+讲解)

右值引用C11 1.左值和右值2.左值引用3.右值引用4.右值引用的性能优化空间5.移动语义6.值类别7.将左值转化为右值8.万能引用和引用折叠9.完美转发10.针对局部变量和右值引用的隐士类型转换11.总结 今天看到谢丙堃老师的《现代C语言核心特性解析》一书中关于右值引用的介绍&#…

21.网络编程|Java学习笔记

文章目录 网络的相关概念ipv4地址分类网路通信协议TCP和UDP InetAdress类SocketTCP网络通信编程应用案例服务端客户端 netstat指令TCP网络通讯不为人知的秘密 UDP网络通信编程【了解】网络传输文件代码示例 网络的相关概念 网络通信 网络 ip地址 1. 概念:用于唯一标识网络…

【数据库原理与应用 - 第七章】数据库安全性和完整性控制

目录 一、数据库安全性控制 二、数据库完整性控制 三、课后习题 数据库的保护功能&#xff1a;数据库安全性、完整性、数据库恢复、并发控制 一、数据库安全性控制 数据库的安全性&#xff1a;保护数据库&#xff0c;以防止非授权用户非法存取造成的数据泄密、更改、破坏DBM…

Python开发中的常见问题和解决方法:如何解决常见的性能和bug问题

第一章&#xff1a;引言 在Python开发中&#xff0c;我们经常会遇到一些常见的问题&#xff0c;包括性能瓶颈和程序错误&#xff08;bug&#xff09;。这些问题可能会影响我们的应用程序的运行效率和稳定性。因此&#xff0c;了解这些问题的根源并学习解决方法是非常重要的。本…

IDEA集成GitHub - Gitee集成

GitHub 集成 实际的开发中&#xff0c;代码都是采用IDE进行开发&#xff0c;所以我们这里介绍一下IDEA软件是如何集成GitHub远程仓库进行代码版本控制的。这里采用的IDEA版本为2022.2.1,其他版本的IDEA软件会略有差别。 1、 配置 Git 软件 2、 配置 GitHub 账号 继续点授权按…

三.数据类型

目录 1、布尔类型 2、整数类型 3、浮点数类型 4、字符类型 5、字符串类型 6、类型转换 1、布尔类型 Go语言中的布尔类型与其他语言基本一致&#xff0c;关键字也为bool&#xff0c;可赋值为预定义的true和false 示例代码如下&#xff1a; var v1 bool v1 true v2 :…

【TCP/IP】利用I/O复用技术实现并发服务器 - select函数

目录 I/O复用技术 select函数 设置文件描述符 指定监视范围 设置超时 I/O复用服务器端的实现 由服务器创建多个进程来实现并发的做法有时会带来一些问题&#xff0c;比如&#xff1a;内存上的开销、CPU的大量占用等&#xff0c;这些因素会消耗掉服务器端有限的计算资源、…

chatgpt赋能python:Python中如何更新pip版本

Python中如何更新pip版本 Python是一种非常强大的编程语言&#xff0c;它在现代编程领域中广泛使用。使用Python的好处之一是能够轻松地在其上安装和使用各种库&#xff0c;其中许多库由Python包管理器pip&#xff08;pip-installs-packages&#xff09;提供。尽管pip可以使Py…

新建的springboot 项目往往删除(1).mvn(2) .gitignore(3) HELP.md (4)mvnw (5)mvnw.cmd 文件

问题 新建的springboot 项目&#xff0c;项目开发人员往往删除&#xff08;1&#xff09;.mvn&#xff08;2&#xff09; .gitignore&#xff08;3&#xff09; HELP.md &#xff08;4&#xff09;mvnw &#xff08;5&#xff09;mvnw.cmd 文件&#xff0c;这些文件是什么&…

康耐视3D相机-DSMAX-VisionPro软件安装向导

机器视觉Halcon-字符识别 一. 系统需求 PC最小需求. OS: Win7 Pro/8Pro/10Pro X64 . Memory: 4GB RAM . PCIe 槽:X4 Gen2 一个 . 显存大小大于1GB 注意:1)PCIe插槽推荐使用x4 Gen 3; 软件版本VisionPro 9.2 CR1 X64/VisionPro 9.5及以上版本+ VisionPro_9_2_CR1_64-bit_…

合宙Air724UG Cat.1模块硬件设计指南--开关机

开关机 简介 模块支持上电后的开机、关机、复位三种状态&#xff0c;本章节会对其进行相应的介绍。 特性 PWRKEY&#xff1a; VILmin0V&#xff0c;VILmax0.5V&#xff0c;推荐值0.1V以下&#xff1b; 引脚状态&#xff1a;模块供电后PWRKEY内部拉高&#xff0c;满足低电平输入…

【哈佛积极心理学笔记】第22讲 自尊与自我实现

第22讲 自尊与自我实现 Unconditional self-esteem is the highest level, the level that Maslow would talk about “the self-actualization”, what David Schnarch talks about as “differentiated” or at the level of being known rather than desiring to be valida…