当前位置: 首页 > news >正文

Vue 3 项目实战教程大事件管理系统 (一):从零开始搭建项目基础

文章目录

  • 技术栈介绍
  • 1.包管理工具pnpm的安装
  • 2.调整项目目录
  • 3.VueRouter4路由语法规则
  • 4.引入 element-ui 组件库
  • 5.Pinia - 构建用户仓库 和 持久化
    • 5.1 基本配置-构建用户仓库和开启持久化
    • 5.2 优化-pinia 独立维护和仓库统一导出
      • 5.2.1 pinia 独立维护
      • 5.2.2 仓库统一导出
  • 6. 数据交互-请求工具设计

技术栈介绍

本项目的技术栈 本项目技术栈基于 ES6、vue3、pinia、vue-router 、vite 、axios 和 element-plus

1.包管理工具pnpm的安装

pnpm优势:比同类工具快 2倍 左右、节省磁盘空间

安装方式:mac 系统要加 sudo 提升为管理员权限

 sudo npm install -g pnpm

安装pnpm 版本为:10.12.4
创建项目:

pnpm create vue

在这里插入图片描述

项目初始化完成,可执行以下命令:

cd Vue3-big-event-admin
pnpm install
pnpm dev

2.调整项目目录

默认生成的目录结构不满足我们的开发需求,所以这里需要做一些自定义改动。主要是两个工作:删除文件和修改内容

  • 删除初始化的默认文件
  • 修改剩余代码内容
  • 新增调整我们需要的目录结构
  • 拷贝初始化资源文件,安装预处理器插件

router/index.js

在这里插入图片描述

删掉stores 中的 js 文件
删掉views 中的.vue 文件
将 assets 文件夹中的内容删除
将main.js 中的导入 css 删除

将 app.vue 清

<script setup>
</script><template><div>我是 App.vue</div>
</template><style scoped></style>

新建文件夹 api 和 utils

将下面的静态资源放入到 assets 文件夹中
在这里插入图片描述

将 main.scss 导入进 main.js 中,需要安装scss 预处理

pnpm add sass -D

下完之后导入进去

import '@/assets/main.scss'

3.VueRouter4路由语法规则

默认代码如下:

import { createRouter, createWebHistory } from 'vue-router'//createRouter创建路由实例
//配置 history 模式: createWebHistory  地址栏不带#
//配置 hash 模式:     createHashHistory 地址栏带#
const router = createRouter({history: createWebHistory(import.meta.env.BASE_URL),routes: []
})export default router

在 app.vue 写两个按钮模拟路由跳转
$router.push(‘’)和 Vue2 一样
但是如果点击事件是自定义的函数,就和 Vue2 的不同了,在 Vue3 CompositionAPI 中

  1. 获取路由对象 const router=useRouter()
  2. //获取路由参数 const route =useRoute()

在这里插入图片描述
在这里插入图片描述
代码如下:

<script setup>
import {useRoute,useRouter} from 'vue-router'
//Vue3 中 获取路由对象 router
const router=useRouter()
//获取路由参数 route
const route =useRoute()const goList=()=>{console.log(router,route)router.push('list')
}
</script><template><div>我是 App.vue<button @click="$router.push('/home')">跳首页</button><button @click="goList">跳列表页</button></div>
</template><style scoped></style>

在路由配置中的这一项:history: createWebHistory(import.meta.env.BASE_URL),
把import.meta.env.BASE_URL改成/TB,效果如下:
在这里插入图片描述
路径前面会多 TB
import.meta.env.BASE_URL是一个参数,在vite.config.js中修改
在这里插入图片描述

4.引入 element-ui 组件库

官方文档: https://element-plus.org/zh-CN/

按照官方文档:
安装:

pnpm install element-plus

快速开始按需引入:

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

对照文档中给出的内容进行比对配置:
在这里插入图片描述
配置完成后重启项目

pnpm dev

把 button 改成 el-button 测试效果,补充:默认下 components 下的文件也会被自动注册

<el-button @click="$router.push('/home')">跳首页</el-button >
<el-button  @click="goList">跳列表页</el-button >

在这里插入图片描述

5.Pinia - 构建用户仓库 和 持久化

5.1 基本配置-构建用户仓库和开启持久化

在创建 Vue 脚手架时,已经导入好了 pinia,现在开启 pinia 的持久化,完成持久化配置
官方文档:https://prazdevs.github.io/pinia-plugin-persistedstate/zh/

安装包依赖:

pnpm add pinia-plugin-persistedstate

将插件添加到你的 pinia 实例中
在这里插入图片描述
配置 stores/user.js

import { defineStore } from 'pinia'
import { ref } from 'vue'export const useStore = defineStore('big-user',() => {const token = ref('') // 定义 tokenconst setToken = (newToken) => (token.value = newToken) // 设置 tokenconst removeToken=()=>{token.value=''}return { token,setToken,removeToken }},{persist: true,},
)

在 app.vue 中测试 pinia

//导入 pinia
import {useUserStore} from '@/stores/user'
const userStore=useUserStore()<p>{{ userStore.token }}</p>
<el-button @click="userStore.setToken('qrafdsgsdfs')">登入</el-button >
<el-button @click="userStore.removeToken">退出</el-button >

在这里插入图片描述

5.2 优化-pinia 独立维护和仓库统一导出

5.2.1 pinia 独立维护

  • 现在:初始化代码在 main.js 中,仓库代码在 stores 中,代码分散职能不单一

  • 优化:由 stores 统一维护,在 stores/index.js 中完成 pinia 初始化,交付 main.js 使用

在 main.js 中拿走和 pinia 有关的代码放到 stores 下的 index.js

移除前的 main.js
在这里插入图片描述
移除后的 main.js和移除后的 index.js

在这里插入图片描述

重新启动服务

pnpm dev

5.2.2 仓库统一导出

  • 现在:使用一个仓库 import { useUserStore } from ./stores/user.js 不同仓库路径不一致

  • 优化:由 stores/index.js 统一导出,导入路径统一 ./stores,而且仓库维护在 stores/modules 中

随着项目的扩大,将 stores 下面的 js 内容放到了 modules文件夹内
如果想在 app.vue 中导入就要写

import {useUserStore} from '@/stores/modules/user'

这样太麻烦了,希望改成如下情况,有 stores 下面的 index.js 统一管理

import {useUserStore,XXXStore} from '@/stores'

在改写 index.js

import{useUserStore} from './modules/user'
export{useUserStore} //假设还有一个 store
import{useCountStore} from './modules/user'
export{useCountStore} 

这样写还是麻烦,改为更简单的方法

export * from './modules/user'
export * from './modules/counter'

6. 数据交互-请求工具设计

一开始做项目的时候,确实可以直接用 axios 请求接口数据,不需要配置什么拦截器
但随着项目越来越复杂,你就会发现这样写代码有一堆问题

写在utils/request.js
首先按照 axios

pnpm add axios
1.每个请求都要手动加 token,很麻烦
axios.get('/api/userinfo', {headers: {Authorization: store.token}
})
你有 20 个接口,就要写 20 次 headers,改 token 也要改 20 次。2.错误提示要手动写,容易忘
axios.get('/api/userinfo').then(res => {if (res.data.code !== 0) {ElMessage.error(res.data.message)}})你会发现:所有接口都要加 if...else,非常重复,而且不统一,UI 上也不好看。
3.token 过期时跳登录,没法统一处理
.catch(err => {if (err.response.status === 401) {router.push('/login')}
})
太繁琐有了拦截器,一切就变得自动化了!
// 请求拦截器:自动加 token
// 响应拦截器:自动弹提示 + 跳登录
你只需要这样用就行了:
request.get('/my/userinfo')
无需关注 token、错误码、跳转页面,所有的逻辑已经帮你封装好了。

统一封装 axios 请求模板:
官方文档:http://www.axios-js.com/zh-cn/docs/#axios-create-config

import axios from 'axios'const baseURL = 'http://big-event-vue-api-t.itheima.net'const instance = axios.create({// 1. 基础地址,超时时间(配置项)
})//请求拦截器
instance.interceptors.request.use((config) => {// 2. 携带token,将 token 值赋给请求头return config},(err) => Promise.reject(err)
)//响应拦截器
instance.interceptors.response.use(
//http 返回 200 成功(res) => {  // 3. 正确拿到了业务数据// 4. 业务逻辑错误,例如限制密码字母大写return res},(err) => {// 5. 处理http 返回401错误return Promise.reject(err)}
)export default instance

本项目封装:

//导入 stores axios router 和组件库 element-ui
import { useUserStore } from '@/stores/user'
import axios from 'axios'
import router from '@/router'
import { ElMessage } from 'element-plus'const baseURL = 'http://big-event-vue-api-t.itheima.net'//创建 axios 实例,配置一些默认项,如超时 10 秒
const instance = axios.create({baseURL,timeout: 100000
})//请求拦截器
instance.interceptors.request.use(
//http200 返回正确(config) => {const userStore = useUserStore()//如果有 token,将 token赋值给请求头,为什么是Authorization,见解释 1if (userStore.token) { config.headers.Authorization = userStore.token}return config},//错误抛出错误信息(err) => Promise.reject(err)
)instance.interceptors.response.use((res) => {//业务逻辑正确(code=0),处理如下if (res.data.code === 0) {return res}//业务逻辑错误(code!=0),手动抛出错误信息,ElMessage是组件,type是他的样式ElMessage({ message: res.data.message || '服务异常', type: 'error' })return Promise.reject(res.data)},//如果 http 返回是是 401,表示用户未登入,或者 token 过期,得重新登入(err) => {ElMessage({ message: err.response.data.message || '服务异常', type: 'error' })console.log(err)if (err.response?.status === 401) {router.push('/login')}//其他错误抛出错误信息return Promise.reject(err)}
)
//instance(默认导出)	是你真正用来发请求的 axios 实例
//baseURL 导出整个请求的“基础路径前缀”
export default instance
export { baseURL }

解释 1:为什么是Authorization?
看接口文档,给你的请求头需要什么?
在这里插入图片描述

解释 2:为什么在响应拦截器中 res 中写的返回是 return Promise.reject(res.data),err 写的是这个return Promise.reject(err)?

拦截器分支拿到的内容我们关心什么为什么这么写
res => {}HTTP 200 成功返回业务数据的状态码res.data.code所以 Promise.reject(res.data),把“业务失败信息”抛出去
err => {}网络错误 / 状态码非 200完整错误对象(包含状态码、错误信息)所以 Promise.reject(err),保留完整异常信息给调用方分析

res 关注的是 code=几,表示是哪里自定义的错误的业务逻辑

解释 3:导出使用

// 使用时
import request, { baseURL } from '@/utils/request'
http://www.dtcms.com/a/399268.html

相关文章:

  • 手机Nexus5 安装 Linux(3) - python3
  • vue el-form 自定义校验, 校验用户名调接口查重
  • 大型网站开发团队北京市轨道交通建设管理有限公司网站
  • 【力扣LeetCode】 349_两个数组的交集
  • 学校做好网站建设目的优化优化
  • 【论文阅读】-《Attention Is All You Need》(Transformer)
  • 网站开发工程师任职资格关于建设殡葬网站的报告范文
  • 北京市保障性住房建设投资中心网站6山东省住房和城乡建设部网站首页
  • 【SpringBoot】27 核心功能 - Web开发原理 - Spring MVC中的定制化原理
  • 自动化接口框架搭建分享-pytest
  • 锦州市做网站建设部网站职业资格证查询
  • cpp类与对象
  • 网站建设管理工作沈阳企业免费建站
  • 算法训练.15
  • 【算法】滑动窗口(一)-长度最小的子数组
  • Spring / Spring Boot 常用注解
  • 【SQL中Lag()和LEAD()的用法】
  • 怎么做代理人金沙网站网页界面设计与分析
  • java中设计思想和架构理念
  • 比PostMan更简洁易用,一款国产开源免费的接口管理工具 - PostIn
  • 什么网站管理系统好网络工程师自学难吗
  • JavaEE 初阶第二十四期:网络原理,底层框架的“通关密码”(四)
  • conda安装软件包的通道conda-forge
  • 【数据库】sql基本语句
  • 手机网站应该怎么做建设网站那个公司好
  • linux 常用命令(包含:网络工具、进程管理工具、常用的)
  • Android
  • 产品设计前硬件考虑的事/示波器/EMC/EMI/热敏电阻
  • UE5GAS GameAbility源码解析 CommitAbility
  • 深圳 网站设计公司排名南通建筑人才网