手机网站一键生成app冯耀宗seo视频教程
Vue3 项目实战: 🆗好久没有更新blog,最近在找工作,还有准备考试,哎,😶🌫️爆炸的大环境🥲
内卷开始🌯🌯 本篇文章涉及的技术栈速通链接🔗: 一口气速通Vue3.0、Pinia 状态管理库⁉️
黑马项目接口: 在线演示:https://fe-bigevent-web.itheima.net/login
-
接口文档: https://apifox.com/apidoc/shared-26c67aee-0233-4d23-aab7-08448fdf95ff/api-93850835
-
本项目的技术栈,本项目技术栈基于:ES6、vue3、pinia、vue-router 、vite 、axios 和 element-plus
Vue3 项目搭建:
pnpm 包管理器:
pnpm 是一个现代的包管理器,旨在提高前端项目的性能和效率,
它由 npm 和 yarn 衍生而来,但解决了这两个工具内部存在的问题,并且显著优化了性能和使用场景
安装 pnpm 非常简单,只需运行以下命令: npm i -g pnpm
比同类工具快 2倍 左右、节省磁盘空间… https://www.pnpm.cn/
pnpm create vue # 创建项目: 建议在一个干净的目录下进行创建,并选择相应配置;
# 🆗安装之后 cd 到创建的项目目录下, 安装对应的项目依赖、运行测试项目
pnpm install # 安装项目依赖
pnpm dev # 运行项目dev
#2024/11/10 pnpm 创建Vue3项目;
ESlint、Prettier 代码风格:
ESLint
和 Prettier
是两个非常流行的工具: 它们分别用于:代码质量
、代码格式化
的自动化管理
- ESLint 是一个用于识别和报告 JavaScript 代码中模式的工具,它的目标是使代码更加一致和避免错误
- Prettier 是一个代码格式化工具,它会自动格式化代码,使其符合预定义的风格标准
大部分后端语言天生的规范,而JS 并没有严格的规范,所以通过中间件来进行代码规范,校验;
这两个工具可以单独使用,但通常结合使用,以充分发挥它们优势:VSCode ESLint简单配置
⚠️痛苦的是很多版本ESlint 配置会有不同的变化,不过可以通过GPT快速查找🔍
- 从 ESLint 8.0.0 版本开始,推荐使用
eslint.config.js
文件 - 来替代之前的
.eslintrc.js
或.eslintrc.json
文件;
个人不喜欢ESlint: 而且版本问题很麻烦,后面在详细介绍;这个配置个人觉得挺麻烦: 用于规定、检查代码格式规范
VsCode使用: 安装依赖、并在VsCode配置中添加配置、新版本直接在.prettierrc.json
文件中配置:
{"$schema": "https://json.schemastore.org/prettierrc","singleQuote": true, // 单引号"semi": false, // 无分号"printWidth": 80, // 每行宽度至多80字符"trailingComma": 'none', // 不加对象|数组最后逗号"endOfLine": 'auto' // 换行符号不限制(win mac 不一致)
}
使用时候要注意版本: ESLint9
最低支持 ≥node20
,结合Prettier
直接配置在 .prettierrc.json
不在和之前一样了;
ESLint 校验配置: 直接在eslint.config.js
进行警告配置,此处就不详细介绍了;
husky 代码检查工作流❌
个人强烈吐槽这个,鬼东西… 总之不喜欢,这一集不学了跳过,没啥用感觉鸡肋————161集跳过;
初学者,建议不用太操心这个,等后面有时间在搞,先写好代码。。。
调整项目目录结构:
🆗,先不管乱七八糟的工程管理配置: pnpm create vue
直接创建的目录,某种程度还不能直接开发,还需要稍微调整;
-
删除初始化的默认文件、修改剩余代码内容、新增调整我们需要的目录结构
api包、util包
)、 -
拷贝初始化资源文件,安装预处理器插件本项目使用
sass
) 实际情况根据项目而调整;
删除|修改 初始化默认文件
新增配置需要目录、包资源
为了方便管理,开发习惯新增需要目录 api utils包: api 存放管理API接口目录
、util 项目开发过程中使用的工具包
导入项目需要的全局样式 和 图片文件——>assets 目录
安装 sass
依赖;
VueRouter4 路由配置:
关于Vue2-router3的简单入门👉
Vue3 中使用vue-router
的方式与 Vue2 类似,但在一些细节上有所不同,首先需要安装vue-router@4
版本,
然后引入并创建路由实例,最后将路由挂载到 Vue 应用实例上,示例代码如下:./router/index.js
//和 Vue2不同 Vue3创建路由 由暴漏的函数实现,以及其路由模式;
// createWebHistory() history模式 地址栏不带#
// createWebHashHistory hash模式 地址栏带#
import { createRouter, createWebHistory } from 'vue-router'
//剩下的和Vue2 基本一致
const router = createRouter({history: createWebHistory(import.meta.env.BASE_URL),routes: [],
})export default router
测试使用路由:
<script setup>
//Vue3 需要通过导入函数形式创建出 router路由对象、route路由参数对象
import { useRoute, useRouter } from 'vue-router'
const router = useRouter()
const route = useRoute()//函数形式路由跳转
const goList = () => {router.push('/list')console.log(router, route)//Vue2 写法报错:因为setup 中并没有this的概念//this.$router.push('/list')
}
</script><template><p>APPVue</p><p><button @click="$router.push('/home')">跳转首页</button></p><p><button @click="goList">跳转列表</button></p>
</template>
history 历史模式:
history: createWebHistory(import.meta.env.BASE_URL),
其实本质还是:
history: createWebHistory('/'),
表示请求路径的前缀,
其值映射的是:vite.config.js
配置文件,base
属性
引入 Element Plus 组件库
快速开始 | Element Plus 为了避免异常,所以此处建议跟随官网即可:大致流程👇
- 安装ElementPlus:
pnpm add element-plus
- 安装插件:
pnpm add -D unplugin-vue-components unplugin-auto-import
- 安装依赖插件、
main.JS
中引入,如果需要按需导入: 还需要配置vite.config.ts
🆗, 如此简单就引入了ElementPlus
,值得惊奇的是配置按需导入的依赖:ElementPlusResolver()
不仅仅对Vue进行按需导入,对于自定义的组件也进行管理: 以至于可以不声明直接在页面中使用;
components 下的文件组件也会被自动注册~
不知道是BUG、还是特性~~
Pinia 构建仓库、持久化
Pinia: 是 Vue.js 的一个状态管理库,它是 Vuex 的替代方案,不了解?可以点击这里👉
当然在项目构建时候已经勾选了:Pinia: 通常在stores
进行创建仓库管理;
测试使用:
模拟使用:Pinia管理用户登录,保存Token的操作: 定义一个stores/user.js
模块;
import { defineStore } from 'pinia'
import { ref } from 'vue'// 用户模块 token setToken removeToken
export const useUserStore = defineStore('big-user', () => {const token = ref('')const setToken = (newToken) => { //更新Tokentoken.value = newToken}const removeToken = () => { //删除Tokentoken.value = ''}//暴漏可以使用的属性\函数return {token,setToken,removeToken,}
})
当然还可以通过插件: pinia-plugin-persistedstate
进行持久化; 以防止刷新数据丢失~🥲
安装插件: pnpm add pinia-plugin-persistedstate -D
配置: main.js
、stores/user.js
main.js
import persist from 'pinia-plugin-persistedstate'
...
app.use(createPinia().use(persist))
store
中通过 persist: true
来开启,默认配置使用localStorage存储整个 state
此处有完整案例Demo
这里缺少一个图片,因为文件太大没有上传,后面解压在弄-----也可能会疑问、、、、
集中管理仓库:
什么是Pinia集中管理呢? 其实上面配置以及满足基本需求的,但是如果一个组件需要引入大量的仓库,
为了方便管理: 可以在/stores
目录下创建一个index.js
专门用来管理仓库,并配置Pinia信息;
main.js: 也只需要注入一个/stores/index.js
不需要在思考其他的配置;
🤮吐槽一下,呃呃呃,为什么这样呢?配置拆来拆去的好烦❗❗
/stores/index.js: Pinia核心配置文件、当然main
//在index中管理pinia 持久化;
import { createPinia } from 'pinia'
import persist from 'pinia-plugin-persistedstate'const pinia = createPinia()
pinia.use(persist)//暴漏pinia
export default pinia
//管理暴漏pinia的仓库
export * from './modules/user'
//export * from './modules/更多仓库' 这样只需要导入一个index 就可以使用任何仓库了;
数据请求工具
实际开发过程中,我们通常会将: axios
进行封装成一个模块进行使用,主要出于以下几个关键原因:
-
统一配置: 通过封装,可以统一管理API请求设置统一的基础URL、默认配置
如:超时时间、headers等、以及处理跨域问题,开发者无需在重复这些配置,提高了代码的可维护性;
-
多环境配置: 随着项目业务越来越大可能:一个前端会有多个服务器配置,定义封装
axios
实现多数据源; -
环境变量管理: 在不同的环境:
开发
、测试
、生产
,基础URL和其他配置可能不同,封装可以轻松地环境变量切换;
定义\封装axios:
首先,安装axios依赖: npm install axios
或 yarn add axios
或 pnpm add axios
新建 src/utils/request.js
封装 axios 模块: 利用 axios.create
创建一个自定义的 axios
来使用;
import axios from 'axios'
import router from '@/router'
import { useUserStore } from '@/stores'
import { ElMessage } from 'element-plus'
const baseURL = 'http://big-event-vue-api-t.itheima.net'const instance = axios.create({// TODO 1. 基础地址,超时时间baseURL,timeout: 10000
})// 请求拦截器
instance.interceptors.request.use((config) => {// TODO 2. 携带tokenconst useStore = useUserStore()if (useStore.token) {config.headers.Authorization = useStore.token}return config},(err) => Promise.reject(err)
)// 响应拦截器
instance.interceptors.response.use((res) => {// TODO 4. 摘取核心响应数据if (res.data.code === 0) {return res}// TODO 3. 处理业务失败// 处理业务失败, 给错误提示,抛出错误ElMessage.error(res.data.message || '服务异常')return Promise.reject(res.data)},(err) => {// TODO 5. 处理401错误// 错误的特殊情况 => 401 权限不足 或 token 过期 => 拦截到登录if (err.response?.status === 401) {router.push('/login')}// 错误的默认情况 => 只要给提示ElMessage.error(err.response.data.message || '服务异常')return Promise.reject(err)}
)export default instance
export { baseURL }
项目路由设计
🆗,终于到项目阶段: 既然需要设计路由,那么让我们来看一下这个项目的情况吧,当然时间情况看的是UL图
黑马项目接口: 在线演示:https://fe-bigevent-web.itheima.net/login
- 接口文档: https://apifox.com/apidoc/shared-26c67aee-0233-4d23-aab7-08448fdf95ff/api-93850835
- 本项目的技术栈,本项目技术栈基于:ES6、vue3、pinia、vue-router 、vite 、axios 和 element-plus
完成整体路由规划【搞清楚要做几个页面,它们分别在哪个路由下面,怎么跳转的…】
通过观察, 点击左侧导航, 右侧区域在切换, 那右侧区域内容一直在变, 那这个地方就是一个路由的出口,大致如下:
path | 文件 | 功能 | 组件名 | 路由级别 |
---|---|---|---|---|
/login | views/login/LoginPage.vue | 登录&注册 | LoginPage | 一级路由 |
/ | views/layout/LayoutContainer.vue | 布局架子 | LayoutContainer | 一级路由 |
├─ /article/manage | views/article/ArticleManage.vue | 文章管理 | ArticleManage | 二级路由 |
├─ /article/channel | views/article/ArticleChannel.vue | 频道管理 | ArticleChannel | 二级路由 |
├─ /user/profile | views/user/UserProfile.vue | 个人详情 | UserProfile | 二级路由 |
├─ /user/avatar | views/user/UserAvatar.vue | 更换头像 | UserAvatar | 二级路由 |
├─ /user/password | views/user/UserPassword.vue | 重置密码 | UserPassword | 二级路由 |
路由文件设计:
为了方便管理,相同的路由可以定义一个在文件夹方便管理: 在views
目录下创建管理文件;
views/login/LoginPage.vue
登录页面:
<template>登录页</template>
views/layout/LayoutContainer.vue
布局页面:因为此页面中嵌套子路由页面,比较特殊;
<template><div>布局架子<!-- 嵌套子集路由组件 --><router-view></router-view></div>
</template>
… 省略 … 其他 … 文件描述
配置路由文件:
router/index.js
🆗,页面文件定义好了,就开始配置路由规则了:
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')}]}],
})
path
:路由的路径、component
:指定与该路由对应的组件redirect
:重定向路径、children
:子路由配置,包含了子路由的路径和对应的组件
App.vue 路由入口:
<script setup></script><template><!-- 清除之前测试代码,引入一个路由组件入口 --><div><router-view></router-view></div>
</template><style scoped></style>
登录、注册业务开发:
登录、注册页面开发:
页面部门就不详细介绍了,看视频去吧:~~ 现在AI很强大,几句话就可以轻松的生成一个页面;
# 安装icons 图标组件
pnpm i @element-plus/icons-vue
登录、注册表单校验:
关于表单校验: 是开发过程中非常重要的作用:确保数据准确性、提升用户体验、数据安全、缓解服务器压力……
在 Vue.js 中使用 Element UI 进行表单校验:,可以说非常简单,只需要简单的配置一下即可;
const rules = {username: [//长度校验 min:xx, max: xx//非空校验required message消息提示 trigger触发校验的时机{ required: true, message: '请输入用户名', trigger: 'blur' },{ min: 5, max: 10, message: '用户名必须是 5-10位 的字符', trigger: 'blur' }],password: [//正则校验 pattern: 正则规则 \S 非空字符{ required: true, message: '请输入密码', trigger: 'blur' },{ pattern: /^\S{6,15}$/,message: '密码必须是 6-15位 的非空字符',trigger: 'blur' }],repassword:[//正则校验 pattern: 正则规则 \S 非空字符{ required: true, message: '请输入密码', trigger: 'blur' },{ pattern: /^\S{6,15}$/,message: '密码必须是 6-15位 的非空字符',trigger: 'blur' },{ //自定义表单校验规则函数,validator: (rule, value, callback) => {//判断value当前form中收集的password是否一致if (value !== formModel.value.password) {callback(new Error('两次输入密码不一致'))// 就算校验成功,也需要callback} else { callback() }},trigger: 'blur'}]
}
注册—接口对接:
写着写着突然发现,黑马接口不能用了,完蛋玩意,算了谁让我是后端呢… 正好有一个后端小Demo
刚想着自己写一个后端服务,结果最近加班就临时搁置了,现在服务又好了,将就着学习吧
//注册按钮点击:
const register = async () => {// 注册成功之前,先进行校验,await form.value.validate()//校验成功 → 请求注册,校验失败 → 自动提示await userRegisterService(formModel.value) //调用注册接口ElMessage.success('注册成功')isRegister.value = false
}
登录—存Token:
注册说到底只是简单的,请求响应,而登录— 往往是一个项目的开始、也是需要逻辑交互的开始….
且前端开发需要控制很多的细节、因为是距离用户最近的软件, 后端领导开不见摸不着的,往那一坐就是一天
//导入pinia的仓库、vue路由
import { useUserStore } from '@/stores'
import { useRouter } from 'vue-router'
//pinia的仓库、vue路由对象
const userStore = useUserStore()
const router = useRouter()
//登录按钮点击
const login = async () => {await form.value.validate()const res = await userLoginService(formModel.value)//登录成功存储TokenuserStore.setToken(res.data.token)ElMessage.success('登录成功')router.push('/')
}//切换的时候重置表单内容
//因为登录、注册是一个公共的表单对象,所以每次切换为了用户体验,监听清空数据
watch(isRegister, () => {formModel.value = {username: '',password: '',repassword: ''}
})
如此:之后的每个请求都会自动携带Token 进行请求——
路由守卫
上述完成了登录,但是发现——: 即使、不登录情况下依然可以进入页面——这显然是不合理的;
还需要一个路由守卫,对所有的请求、路由进行拦截、判断: 是否携带Token,才允许继续操作,不然全拦截登录页
src/router/index:配置全局路由守卫🥷🥷
import { useUserStore } from '@/stores'
// 登录访问拦截 => 默认是直接放行的
// 根据返回值决定,是放行还是拦截
// 返回值:
// 1. undefined / true 直接放行
// 2. false 拦回from的地址页面
// 3. 具体路径 或 路径对象 拦截到对应的地址
// '/login' { name: 'login' }
router.beforeEach((to) => {// 如果没有token, 且访问的是非登录页,拦截到登录,其他情况正常放行const useStore = useUserStore()if (!useStore.token && to.path !== '/login') return '/login'
})
总结:
🆗, 兄弟们到此,Vue从零开始——Vue3就完结🎉🎉
感谢黑马、免费教程—— 真的对小白太友好,
至于后面的内容,需要手动操作——CRDU,CV战士
且现在大部分公司都用成形框架,对Vue+Elment进行二次封装
表单、表格组件化——只需要配置JS配置——甚至AI自动化就完成了
一套页面的CRUD甚至不用手写代码;
突然想如果想要成为架构师方向,可以去找一个现在成熟的框架源码去研究、魔改成自己的框架;
总结:
🆗, 兄弟们到此,Vue从零开始——Vue3就完结🎉🎉
感谢黑马、免费教程—— 真的对小白太友好,
至于后面的内容,需要手动操作——CRDU,CV战士
且现在大部分公司都用成形框架,对Vue+Elment进行二次封装
表单、表格组件化——只需要配置JS配置——甚至AI自动化就完成了
一套页面的CRUD甚至不用手写代码;
突然想如果想要成为架构师方向,可以去找一个现在成熟的框架源码去研究、魔改成自己的框架;
草稿区:
Vscode Git插件使用
注意最后别忘记了,整理项目需要的图片资源,放在一个包里面
git branch -D <分支名称>
:强制删除指定分支,不论其是否已合并
git branch -d <分支名称>
:删除指定分支,前提是该分支已合并到其他分支
-
Branch 创建分支切换指定版本:可以到这边看代码—操作—然后不影响Master,不需要直接删除
-
Soft 软重置到指定版本:切换到该版本,但代码不变,如果此时提交则会覆盖过程中的版本,不可逆操作
谨慎使用: 在没做任何操作之前可以
git reflog
命令查看操作历史记录,找到软重置之前的提交哈希值使用
git reset --hard <提交哈希值>
命令,将分支恢复到指定的提交,从而恢复到之前的操作状态 -
Hard 硬重置到这个提交,这意味着将当前分支的指针直接指向指定的提交,同时会丢弃指定提交之后的所有本地修改
-
Tag 给当前版本创建标签,方便管理快速查询,
-
More 中会出现很多命令,方便快速使用;
写着写着突然发现,黑马接口不能用了,完蛋玩意,算了谁让我是后端呢… 正好有一个后端小Demo
- SpringSecurity 速速上手_需要的朋友可以自取代码,当然需要一些改造;
- 最终版Jar 最后统一打包放在文件中… 什么有人不会Java 那么就用Node写一个简单的Server