【VUE3】练习项目——大事件后台管理

目录

0 前言

1 准备工作

1.1 安装pnpm

1.2 创建vue项目

1.3 Eslint & Prettier的配置

1.4 husky 提交代码检查

1.5 目录调整

1.6 VueRouter4

1.6.1 基础配置

1.6.2 路由跳转

1.7 引入 Element Plus 组件库

1.8 Pinia

1.8.1 优化 

1.9 封装请求工具

1.9.1 安装 axios 与配置框架

1.9.2 示例代码

2 开发


0 前言

黑马程序员视频地址:Vue3大事件项目-项目介绍和pnpm创建项目

接口文档:登录 - 黑马程序员-大事件 


1 准备工作

1.1 安装pnpm

官网:pnpm - 速度快、节省磁盘空间的软件包管理器 | pnpm中文文档 | pnpm中文网

安装pnpm命令:

npm i pnpm -g

pnpm创建vue项目命令:

pnpm create vue

命令对比: 

npmyarnpnpm
npm installyarnpnpm install
npm install axiosyarn add axiospnpm add axios
npm install axios -Dyarn add axios -Dpnpm add axios -D
npm uninstall axiosyarn remove axiospnpm remove axios
npm run devyarn devpnpm dev

1.2 创建vue项目

使用pnpm创建vue项目时,选择以下配置

请选择要包含的功能: (↑/↓ 切换,空格选择,a 全选,回车确认)
|  [ ] TypeScript
|  [ ] JSX 支持
|  [+] Router(单页面应用开发)
|  [+] Pinia(状态管理)
|  [ ] Vitest(单元测试)
|  [ ] 端到端测试
|  [+] ESLint(错误预防)
|  [+] Prettier(代码格式化)

标记:警告提示(待解决)

 创建完项目需要进入相应文件夹中,安装所有依赖

pnpm install

1.3 Eslint & Prettier的配置

见 【VUE3】Eslint 与 Prettier 的配置-CSDN博客

推荐使用里面的方案二,即将 prettier 的规则让 eslint 来执行

因为 1.4 中的检查代码需要 eslint 来检查


1.4 husky 提交代码检查

husky 是一个 git hooks 工具  ( git的钩子工具,可以在特定时机执行特定的命令 )

第一步:初始化仓库

git init

第二步:初始化 husky 工具配置

pnpm dlx husky-init; pnpm install

第三步:修改 .husky/pre-commit 文件

pnpm lint

但是这样会有一个问题! 

我们可以打开 package.json 文件,看到里面的 lint 命令对应为:

"lint": "eslint . --fix"

即默认进行的是全量检查,耗时问题,历史问题,因此需要再导入一个包 lint-staged :

第一步:安装

pnpm i lint-staged -D

第二步:配置 package.json 文件

{// ... 省略 ..."lint-staged": {"*.{js,ts,vue}": ["eslint --fix"]}
}{"scripts": {// ... 省略 ..."lint-staged": "lint-staged"}
}

第三步:修改 .husky/pre-commit 文件

pnpm lint-staged

这样就会只检查修改过的文件,哪怕以前提交的文件有问题,也不会检查报错

可以通过控制 1.3 中的那篇文章的第七节中的 'no-undef': 'off'来模拟提交以前有问题的文件


1.5 目录调整

删除默认文件后,增加 api 与 utils 文件夹

如果使用 sass,则需安装对应依赖

pnpm add sass -D

1.6 VueRouter4

更多内容见官网:Vue Router | Vue.js 的官方路由 

1.6.1 基础配置

import { createRouter, createWebHistory } from 'vue-router'// createRouter 创建路由实例,===> new VueRouter()
// 1. history模式: createWebHistory()   http://xxx/user
// 2. hash模式: createWebHashHistory()  http://xxx/#/user// vite 的配置 import.meta.env.BASE_URL 是路由的基准地址,默认是 ’/‘
// https://vitejs.dev/guide/build.html#public-base-path// 如果将来你部署的域名路径是:http://xxx/my-path/user
// vite.config.ts  添加配置  base: my-path,路由这就会加上 my-path 前缀了const router = createRouter({history: createWebHistory(import.meta.env.BASE_URL),routes: []
})export default router

1.6.2 路由跳转

由于 setup 下,this 指向 undefined ,因此需要引入包创建 router 与 router 对象

<script setup>
import { useRoute, useRouter } from 'vue-router'
const router = useRouter()
const route = useRoute()
const gotoCart = () => {console.log(route)router.push('/individual')
}
</script><template><div>我是App</div><button @click="gotoCart()">跳转购物车页面</button>
</template>

1.7 引入 Element Plus 组件库

官方手册:一个 Vue 3 UI 框架 | Element Plus

安装组件库

pnpm install element-plus

按需引入:

第一步:安装插件

pnpm add -D unplugin-vue-components unplugin-auto-import

 第二步:把下列代码插入到你的 Vite 的配置文件中

import { defineConfig } from 'vite'
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'export default defineConfig({// ...plugins: [// ...AutoImport({resolvers: [ElementPlusResolver()],}),Components({resolvers: [ElementPlusResolver()],}),],
})

全部引入此处不赘述 

注意:

1.在引入之后,无需任何配置,即可使用组件库内的组件

2.并且components下的vue组件也可以直接使用,无需导入


1.8 Pinia

见文档:【VUE3】Pinia-CSDN博客

注意:由于创建项目时勾选了Pinia,所以此处不需要再手动安装配置Pinia,直接可以使用

但是持久化还需手动配置,此处不再赘述

1.8.1 优化 

将 main.js 中关于 pinia 的代码抽离到 store/index.js 中,并且将 store/modules 中的所有仓库文件统一从 index.js 中导出,方便管理且简化代码 

// main.js
// ...
import pinia from './stores'// ...
app.use(pinia)// ...
// store/index.jsimport { createPinia } from 'pinia'
import persist from 'pinia-plugin-persistedstate'const pinia = createPinia()
pinia.use(persist)export default piniaexport * from '@/stores/modules/user'
export * from '@/stores/modules/count'// 上面的代码等同于
// import { useUserStore, ... } from '@/stores/modules/user'
// export { useUserStore, ... }
// 组件.vueimport { useUserStore, useCountStore } from '@/stores'const userStore = useUserStore()
const userCount = useCountStore()

1.9 封装请求工具

手册:axios中文文档|axios中文网 | axios 

1.9.1 安装 axios 与配置框架

1.安装 axios

pnpm add axios

2.框架代码

// utils/request.jsimport axios from 'axios'const baseURL = 'http://big-event-vue-api-t.itheima.net'const instance = axios.create({// TODO 1. 基础地址,超时时间
})instance.interceptors.request.use((config) => {// TODO 2. 携带tokenreturn config},(err) => Promise.reject(err)
)instance.interceptors.response.use((res) => {// TODO 3. 处理业务失败// TODO 4. 摘取核心响应数据return res},(err) => {// TODO 5. 处理401错误return Promise.reject(err)}
)export default instance

1.9.2 示例代码

// utils/request.jsimport axios from 'axios'
import { useUserStore } from '@/stores'
import { ElMessage } from 'element-plus'
import router from '@/router'
const baseURL = 'http://big-event-vue-api-t.itheima.net'const instance = axios.create({// TODO 1. 基础地址,超时时间baseURL,timeout: 100000
})instance.interceptors.request.use((config) => {// TODO 2. 携带tokenconst userStore = useUserStore()if (userStore.token) {config.headers.Authorization = userStore.token}return config},(err) => Promise.reject(err)
)instance.interceptors.response.use((res) => {// TODO 3. 处理业务失败if (res.data.code === 0) {return res}ElMessage({ message: res.data.message || '服务异常', type: 'error' })// TODO 4. 摘取核心响应数据return Promise.reject(res.data)},(err) => {ElMessage({ message: err.response.data.message || '服务异常', type: 'error' })// TODO 5. 处理401错误if (err.response?.status === 401) {router.push('/login')}return Promise.reject(err)}
)export default instance

2 开发

2.1 路由配置

示例:采用 路由懒加载

// router/index.jsimport { createRouter, createWebHistory } from 'vue-router'const router = createRouter({history: createWebHistory(import.meta.env.BASE_URL),routes: [{ path: '/login', component: () => import('@/views/login/LoginPage.vue') },{path: '/',component: () => import('@/views/layout/LayoutContainer.vue'),redirect: '/article/manage',children: [{ path: '/article/manage', component: () => import('@/views/article/ArticleManage.vue') },{ path: '/article/channel', component: () => import('@/views/article/ArticleChannel.vue') },{ path: '/user/profile', component: () => import('@/views/user/UserProfile.vue') },{ path: '/user/avatar', component: () => import('@/views/user/UserAvatar.vue') },{ path: 'user/password', component: () => import('@/views/user/UserPassword.vue') }]}]
})export default router

记得准备路由出口,如:

// App.vue<template><router-view></router-view>
</template>

2.2 登录注册

2.2.1 静态页面

1.安装 element-plus 图标库

pnpm i @element-plus/icons-vue

2.静态结构准备

注意:登录页面与注册页面使用 v-if 与 v-else 控制切换

// views/login/LoginPage.vue<script setup>
import { User, Lock } from '@element-plus/icons-vue'
import { ref } from 'vue'
const isRegister = ref(true)
</script><template><el-row class="login-page"><el-col :span="12" class="bg"></el-col><el-col :span="6" :offset="3" class="form"><el-form ref="form" size="large" autocomplete="off" v-if="isRegister"><el-form-item><h1>注册</h1></el-form-item><el-form-item><el-input :prefix-icon="User" placeholder="请输入用户名"></el-input></el-form-item><el-form-item><el-input :prefix-icon="Lock" type="password" placeholder="请输入密码"></el-input></el-form-item><el-form-item><el-input :prefix-icon="Lock" type="password" placeholder="请输入再次密码"></el-input></el-form-item><el-form-item><el-button class="button" type="primary" auto-insert-space> 注册 </el-button></el-form-item><el-form-item class="flex"><el-link type="info" :underline="false" @click="isRegister = false"> ← 返回 </el-link></el-form-item></el-form><el-form ref="form" size="large" autocomplete="off" v-else><el-form-item><h1>登录</h1></el-form-item><el-form-item><el-input :prefix-icon="User" placeholder="请输入用户名"></el-input></el-form-item><el-form-item><el-inputname="password":prefix-icon="Lock"type="password"placeholder="请输入密码"></el-input></el-form-item><el-form-item class="flex"><div class="flex"><el-checkbox>记住我</el-checkbox><el-link type="primary" :underline="false">忘记密码?</el-link></div></el-form-item><el-form-item><el-button class="button" type="primary" auto-insert-space>登录</el-button></el-form-item><el-form-item class="flex"><el-link type="info" :underline="false" @click="isRegister = true"> 注册 → </el-link></el-form-item></el-form></el-col></el-row>
</template><style lang="scss" scoped>
.login-page {height: 100vh;background-color: #fff;.bg {background:url('@/assets/logo2.png') no-repeat 60% center / 240px auto,url('@/assets/login_bg.jpg') no-repeat center / cover;border-radius: 0 20px 20px 0;}.form {display: flex;flex-direction: column;justify-content: center;user-select: none;.title {margin: 0 auto;}.button {width: 100%;}.flex {width: 100%;display: flex;justify-content: space-between;}}
}
</style>

2.2.2 规则校验

官方文档:Form 表单 | Element Plus

四大校验方式:

        1.非空校验:required

        2.长度校验:min、max

        3.正则校验:pattern

        4.自定义校验 :validator

第一步:声明表单数据对象与规则对象,其中表单数据对象必须是响应式的 

const formData = ref({username: '',password: '',repassword: ''
})
const formRules = {username: [{ required: true, message: '用户名不能为空!', trigger: 'blur' },// blur是失去焦点事件{ min: 5, max: 10, message: '用户名必须为5-10位字符', trigger: 'blur' }],password: [{ required: true, message: '密码不能为空!', trigger: 'blur' },{ pattern: /^\S{8,15}$/, message: '密码必须为8-15位非空字符', trigger: 'change' }// change为改变时校验,发现当检验提示错误后,若触发失焦事件,会导致提示消失,因此不推荐]
}

第二步:给整个表单的大标签绑定数据对象与规则对象

<el-form
...
:model="formData"
:rules="formRules"
>
<!-- ... -->
</el-form>

第三步:给输入框绑定数据,并且给表单元素标签绑定要使用的规则

<el-form-item prop="username">    ❗<el-input:prefix-icon="User"placeholder="请输入用户名"v-model="formData.username"    ❗></el-input>
</el-form-item>

自定义校验方式:

使用方式相同,只是配置规则时,validator 指向一个函数

参数:

        rule:当前校验规则相关的信息

        value:所校验的表单元素目前的表单值

        callback:无论成功还是失败,都需要 callback 回调

const formRules = {// ...repassword: [{validator: (rule, value, callback) => {if (value !== formData.value.password) {callback(new Error('两次密码不一致,请重新输入!'))} else {callback()}},trigger: 'blur'}]
}

2.2.3 表单预校验

由于vue3的特性,即导入的组件内的方法默认不会暴露,因此需要获取组件对象,然后再获取,如:

第一步:获取组件对象

详细见 【VUE3】组合式API-CSDN博客 中的 9.2

const form = ref()
<el-form
ref="form"    ❗
size="large"
autocomplete="off"
v-if="isRegister"
:model="formData"
:rules="formRules"
>

第二步:调用 validate 方法

validate 方法即对整个表单的内容进行验证,接收一个回调函数,或返回 Promise

const register = async () => {await form.value.validate()    ❗await userRegisterService(formData.value)    // 这个是提交数据apiElMessage.success('注册成功!')isRegister.value = false    // 切换登录
}

注意:因为之前我们设置了插件来帮我们自动导入Element组件,所以上述代码中的ElMessage方法我们没有导入,但是eslint会报错,可以在 eslint.config.js 中来配置,让其不报错,位置及代码如下:

// ...export default defineConfig([// ...{rules: {// ...'vue/no-setup-props-destructure': ['off'], // 放在这个下面globals: {ElMessage: 'readonly',ElMessageBox: 'readonly',ElLoading: 'readonly'}}},
])

2.2.4 封装注册api

// api/user.jsimport request from '@/utils/request'export const userRegisterService = ({ username, password, repassword }) =>request.post('/api/reg', { username, password, repassword })

调用见 2.2.3 


持续更新

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

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

相关文章

WebSocket与MQTT

在物联网&#xff08;IoT&#xff09;领域&#xff0c;​WebSocket和MQTT确实都可以实现实时通信&#xff0c;但它们的核心设计目标、适用场景和角色存在显著差异。以下是两者的对比分析&#xff1a; ​1. 协议设计初衷​ ​WebSocket​ ​目标​&#xff1a;提供浏览器与服务器…

Mysql为什么有时候会选错索引

案例 正常情况 有一个表t ( id, a , b )&#xff0c;id是主键索引&#xff0c;a是Normal索引。 正常情况下&#xff0c;针对a进行查询&#xff0c;可以走索引a 并且查询的数量和预估扫描行数是差不多的&#xff0c;都是10001行 奇怪的现象 随着时间的变化&#xff0c;后…

[250414] ArcoLinux 项目宣布逐步结束

目录 ArcoLinux 项目宣布逐步结束 ArcoLinux 项目宣布逐步结束 备受欢迎的 Arch Linux 发行版 ArcoLinux 近日宣布&#xff0c;其项目将逐步结束。ArcoLinux 以其作为 Linux 教育平台和提供多种安装选项&#xff08;从完整桌面环境到最小化基础安装&#xff09;而闻名。 核心…

opencv人脸性别年龄检测

一、引言 在计算机视觉领域&#xff0c;人脸分析是一个热门且应用广泛的研究方向。其中&#xff0c;人脸性别年龄检测能够自动识别图像或视频流中人脸的性别和年龄信息&#xff0c;具有诸多实际应用场景&#xff0c;如市场调研、安防监控、用户个性化体验等。OpenCV 作为一个强…

【NLP】 22. NLP 现代教程:Transformer的训练与应用全景解读

&#x1f9e0; NLP 现代教程&#xff1a;Transformer的训练与应用全景解读 一、Transformer的使用方式&#xff08;Training and Use&#xff09; 如何使用Transformer模型&#xff1f; Transformer 模型最初的使用方式有两种主要方向&#xff1a; 类似 RNN 编码-解码器的架…

Spring Boot 集成 RocketMQ 全流程指南:从依赖引入到消息收发

前言 在分布式系统中&#xff0c;消息中间件是解耦服务、实现异步通信的核心组件。RocketMQ 作为阿里巴巴开源的高性能分布式消息中间件&#xff0c;凭借其高吞吐、低延迟、高可靠等特性&#xff0c;成为企业级应用的首选。而 Spring Boot 通过其“约定优于配置”的设计理念&a…

HTTPS实现安全的关键方法及技术细节

HTTPS&#xff08;HyperText Transfer Protocol Secure&#xff09;通过多种技术手段实现数据传输的安全性&#xff0c;其核心机制基于SSL/TLS协议&#xff0c;并结合数字证书、加密算法等技术。 SSL&#xff1a;Secure Sockets Layer&#xff0c;安全套接字层 TLS&#xff1a;…

Java【多线程】(8)CAS与JUC组件

目录 1.前言 2.正文 2.1CAS概念 2.2CAS两种用途 2.2.1实现原子类 2.2.2实现自旋锁 2.3缺陷&#xff1a;ABA问题 2.4JUC组件 2.4.1Callable接口 2.4.2ReentrantLock&#xff08;与synchronized对比&#xff09; 2.4.3Semaphore信号量 2.4.4CountDownLatch 3.小结 1…

【Docker】离线安装Docker

背景 离线安装Docker的必要性&#xff0c;第一&#xff0c;在目前数据安全升级的情况下&#xff0c;很多外网已经基本不好访问了。第二&#xff0c;如果公司有对外部署的需求&#xff0c;那么难免会存在对方只有内网的情况&#xff0c;那么我们就要做到学会离线安装。 下载安…

MecAgent Copilot:机械设计师的AI助手,开启“氛围建模”新时代

MecAgent Copilot作为机械设计师的AI助手,正通过多项核心技术推动机械设计进入“氛围建模”新时代。以下从功能特性、技术支撑和应用场景三方面解析其创新价值: 一、核心功能特性 ​​智能草图生成与参数化建模​​ 支持自然语言输入生成设计草图和3D模型,如输入“剖面透视…

MCU屏和RGB屏

一、MCU屏 MCU屏‌&#xff1a;全称为单片机控制屏&#xff08;Microcontroller Unit Screen&#xff09;&#xff0c;在显示屏背后集成了单片机控制器&#xff0c;因此&#xff0c;MCU屏里面有专用的驱动芯片。驱动芯片如&#xff1a;ILI9488、ILI9341、SSD1963等。驱动芯片里…

7.5 使用MobileNet v3进行图像的区分

MobileNet v3是Google在2019年提出的轻量级卷积神经网络结构,旨在提高在移动设备上的速度和准确性,广泛的用于轻量级网络。 MobileNet v3-Small的网络结构如下,它的输入是224x224的3通道彩色图片。 使用过程如下: 1.创建模型、修改最终分类数量 #1.创建mobilenet_v3_small…

构建面向大模型训练与部署的一体化架构:从文档解析到智能调度

作者&#xff1a;汪玉珠&#xff5c;算法架构师 标签&#xff1a;大模型训练、数据集构建、GRPO、自监督聚类、指令调度系统、Qwen、LLaMA3 &#x1f9ed; 背景与挑战 随着 Qwen、LLaMA3 等开源大模型不断进化&#xff0c;行业逐渐从“能跑通”迈向“如何高效训练与部署”的阶…

PostgreSQL技术大讲堂 - 第86讲:数据安全之--data_checksums天使与魔鬼

PostgreSQL技术大讲堂 - 第86讲&#xff0c;主题&#xff1a;数据安全之--data_checksums天使与魔鬼 1、data_checksums特性 2、避开DML规则&#xff0c;嫁接非法数据并合法化 3、避开约束规则&#xff0c;嫁接非法数据到表中 4、避开数据检查&#xff0c;读取坏块中的数据…

【机器学习】机器学习笔记

1 机器学习定义 计算机程序从经验E中学习&#xff0c;解决某一任务T&#xff0c;进行某一性能P&#xff0c;通过P测定在T上的表现因经验E而提高。 eg&#xff1a;跳棋程序 E&#xff1a; 程序自身下的上万盘棋局 T&#xff1a; 下跳棋 P&#xff1a; 与新对手下跳棋时赢的概率…

Ubuntu20.04 设置开机自启

参考&#xff1a; Ubuntu20.04 设置开机自启_ubuntu进bos系统-CSDN博客

数据库中存储过程的流程语句讲解

一、流程语句讲解 二、总结 一、流程语句讲解 1.1 if语句讲解 语法&#xff1a; IF condition THENstatements; ELSEIF condition THENstatements; ELSEstatements; END IF; 题目示例&#xff1a; # 判断成绩等级 # 输入学生的编号,取出学生的第一门课&#xff0c;然后判断…

kubernetes》》k8s》》ConfigMap 、Secret

configmap官网 ConfigMap是一种 API 对象&#xff0c;使用时&#xff0c; Pods 可以将其用作环境变量、命令行参数或者存储卷中的配置文件。ConfigMap将配置和Pod解耦&#xff0c;更易于配置文件的更改和管理。ConfigMap 并不提供保密或者加密功能。 如果你想存储的数据是机密的…

git在IDEA中使用技巧

git在IDEA中使用技巧 merge和rebase 参考&#xff1a;IDEA小技巧-Git的使用 git回滚、强推、代码找回 参考&#xff1a;https://www.bilibili.com/video/BV1Wa411a7Ek?spm_id_from333.788.videopod.sections&vd_source2f73252e51731cad48853e9c70337d8e cherry pick …

Spring 事务失效的原因及解决方案全解析,来复习了

Spring 事务失效是指在使用 Spring 声明式事务管理时&#xff0c;预期的事务行为&#xff08;如事务的开启、提交、回滚等&#xff09;未按预期执行&#xff0c;导致数据操作未满足 ACID 特性&#xff08;原子性、一致性、隔离性、持久性&#xff09;&#xff0c;从而引发数据不…