vue3项目之大事件管理系统(一) 项目介绍和相关配置,下载相关插件和配置路由

一.项目介绍和相关配置

1.技术栈
  • 使用Vue3组件式API
  • 使用Pinia进行持久化处理
  • 使用Element-plus作为组件库(提供表单校验,表格处理和组件封装等功能)
  • 使用升级的包管理工具pnpm
  • 使用ESLint+Prettier作为代码规范
  • 使用husky(Git hook工具)作为代码提交的规范校验
  • 使用VueRouter4作为路由设置和请求模块的设计
  • 尝试使用AI(deepseek或chatGPT),向其提出明确的,描述准确的功能需求,让其返回可为我们所用的代码
2.项目介绍

在线演示:
https://fe-bigevent-web.itheima.net/login
接口文档:
https://apifox.com/apidoc/shared
基地址:
http://big-event-vue-apit.itheima.net/
视频地址:
https://www.bilibili.com/video/BV1HV4y1a7n4

3.安装pnpm并用其创建vue3项目

安装命令:npm install -g pnpm
创建项目:pnpm create vue
配置:

项目名:big-event-admin
包名:同上
是否添加TS:NO
是否添加JSX:No
是否添加VueRouter作为单页面组件的路由:Yes
是否添加:pinia:Yes
单元测试Vitest:No
测试的解决方案:No
是否添加ESLInt:Yes
是否添加Perttier:Yes//专门美化代码的格式化工具

踩坑:遇到了cmd或powershell无法正常显示无法显示配置界面的问题
可能原因是:由于版本兼容问题不能显示交互式界面
当前的解决办法是:先照着视频盲配,后续再解决
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4.ESLint的配置代码风格和Prettier
  • 说明:

ESLint在配置文件.eslintrc.cjs中配置相关代码,负责对不规范代码报错
perttier是专注代码格式化的插件,使代码更美观,是负责美化代码

  • 先把在vscode应用商店中下载的prettier插件禁用,再启用ESLint,然后在settings.json中设置:
//当保存时.,eslint自动修复错误:
"editor.codeActionsOnSave": {
    "source.fixAll.eslint": "explicit"
},
//保存代码,不自动格式化
"editor.formatOnSave": false,
  • 最后,把下面的相关配置代码粘贴到配置文件.eslintrc.cjs
  rules: {
    'prettier/prettier': [
      'warn',
      {
        singleQuote: true, // 单引号
        semi: false, // 无分号
        printWidth: 80, // 每行宽度至多80字符
        trailingComma: 'none', // 不加对象|数组最后逗号
        endOfLine: 'auto' // 换行符号不限制(win mac 不一致)
      }
    ],
    'vue/multi-word-component-names': [
      'warn',
      {
        ignores: ['index'] // vue组件名称多单词组成(忽略index.vue)
      }
    ],
    'vue/no-setup-props-destructure': ['off'], // 关闭 props 解构的校验
    // 💡 添加未定义变量错误提示,create-vue@3.6.3 关闭,这里加上是为了支持下一个章节演示。
    'no-undef': 'error'
  }

踩坑:我的Vue3项目中并不自动生成.eslintrc.cjs文件
原因是这个项目太老了,现在创建vue3项目自动生成的是eslint.config.js文件,配置如下:

//eslint.config.js

import { defineConfig, globalIgnores } from 'eslint/config'
import globals from 'globals'
import js from '@eslint/js'
import pluginVue from 'eslint-plugin-vue'
import pluginOxlint from 'eslint-plugin-oxlint'
import skipFormatting from '@vue/eslint-config-prettier/skip-formatting'

export default defineConfig([
  {
    name: 'app/files-to-lint',
    files: ['**/*.{js,mjs,jsx,vue}'],
  },

  globalIgnores(['**/dist/**', '**/dist-ssr/**', '**/coverage/**']),
  // 基础配置
  {
    languageOptions: {
      globals: {
        ...globals.browser,
      },
    },
  },
  // 自定义规则
  {
    rules: {
      'prettier/prettier': [
        'warn',
        {
          singleQuote: true, // 单引号
          semi: false, // 无分号
          printWidth: 80, // 每行宽度至多80字符
          trailingComma: 'none', // 不加对象|数组最后逗号
          endOfLine: 'auto' // 换行符号不限制(win mac 不一致)
        }
      ],
      'vue/multi-word-component-names': [
        'warn',
        {
          ignores: ['index'] // vue组件名称多单词组成(忽略index.vue)
        }
      ],
      'vue/no-setup-props-destructure': ['off'], // 关闭 props 解构的校验
      // 💡 添加未定义变量错误提示,create-vue@3.6.3 关闭,这里加上是为了支持下一个章节演示。
      'no-undef': 'error'
    }
  },

  js.configs.recommended,
  ...pluginVue.configs['flat/essential'],
  ...pluginOxlint.configs['flat/recommended'],
  skipFormatting,
])

5.基于husky配置代码检查工作流
什么是husky?
基于git的hook工具,理解为git里面的钩子,能在特性时机执行特定命令
场景需求

提交代码到仓库之前做一下检查,确保提交的代码都是规范的

做法
  • 在项目根目录打开gitBash,初始化仓库:git init
  • 下载husky插件:pnpm dlx husky-init$$pnpm install
  • 修改.husky/pre-commit文件如下:
:npm test
改为:pnpm lint
  ==>lint命令是默认在package.json中配置好的,一次性对项目中所有的文件进行校验,并自动修复不规范代码
	但是这样的每次都对全局代码全部校验,效率很低也浪费性能,
	后续应该优化为只对暂存区代码进行校验
如何优化为只对暂存区校验?
  • 安装小插件lint-staged包:pnpm i lint-staged -D
  • 在package.json中配置lint-staged命令:
//package.json

{
  "name": "my-big-event-admin",
  "version": "0.0.0",
  "private": true,
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "preview": "vite preview",
    "lint:oxlint": "oxlint . --fix -D correctness --ignore-path .gitignore",
    "lint:eslint": "eslint . --fix",
    "lint-staged": "lint-staged",
    "lint": "run-s lint:*",
    "format": "prettier --write src/",
    "prepare": "husky install"
  },
  "dependencies": {
    "pinia": "^3.0.1",
    "vue": "^3.5.13",
    "vue-router": "^4.5.0"
  },
  "devDependencies": {
    "@eslint/js": "^9.22.0",
    "@vitejs/plugin-vue": "^5.2.3",
    "@vue/eslint-config-prettier": "^10.2.0",
    "eslint": "^9.22.0",
    "eslint-plugin-oxlint": "^0.16.0",
    "eslint-plugin-vue": "~10.0.0",
    "globals": "^16.0.0",
    "husky": "^8.0.0",
    "npm-run-all2": "^7.0.2",
    "oxlint": "^0.16.0",
    "prettier": "3.5.3",
    "vite": "^6.2.4",
    "vite-plugin-vue-devtools": "^7.7.2"
  },
  "lint-staged": {
    "*.{js,ts,vue}": [
      "eslint --fix"
    ]
  }
}
  • 最后再修改.husky/pre-commit文件
#npm init---不要了
#pnpm lint---不要了
pnpm lint-staged
6.调整Vue3项目的目录

除了代码规范,目录也同样需要规范,因为默认生成的目录结构不满足项目需求,需做一些自定义改动:

  • 删除一些初始化的默认文件
assets,views,components,store等下的子文件(:counter.js)
重置router/index.js中的routes数组(清空路由配置)
  • 新增我们需要的目录结构
创建api(请求模块相关的封装),utils(工具函数相关的封装),这两个目录
  • 拷贝全局样式和图片,安装预处理器
静态资源放到assets (没有静态文件)

下载sass:git bash:pnpm add sass -D (可以下载)
并在main.js中引入:import '@/assets/main.scss'(没有main.scss文件,不导入了)
  • 初始化重要文件如下

src/router/index.js

import { createRouter, createWebHistory } from 'vue-router'

const router = createRouter({
  history: createWebHistory(import.meta.env.BASE_URL),
  routes: []
})

export default router

src/App.vue

<script setup></script>

<template>
  <div>
    <router-view></router-view>
  </div>
</template>

<style scoped></style>

src/main.js

import { createApp } from 'vue'
import { createPinia } from 'pinia'

import App from './App.vue'
import router from './router'

const app = createApp(App)

app.use(createPinia())
app.use(router)
app.mount('#app')

7.VueRouter4对比VueRouter2代码风格上有哪些不同?
vue-router4路由代码解析
之前的:
import VueRouter from "vue-router"
//初始化:vue-router3.x和vue2
const router=new VueRouter({
    mode:'history',//去掉"#"
    route:[]
})
export default router

现在的:
//按需导入
import {{createRouter,createWebHistory}} from 'vue-router'
//初始化:vue-router4.x和vue3
const router=new({
    history:createWebHistory(import.meta.env.BASE_URL),//配置模式(可选值:createWebHistory,createHashHistory)
    route:[]//配置路由规则
})
export default router
路由跳转有哪些变化?
template中,仍然兼容之前写法:$router.push('/')

script中,由于没有this,不能写成this.$router.push('/'),

所以要引入useRouter(),写法如下:
import {useRouter,useRoute} from 'vue-router'
const router=useRouter()//获取路由信息对象router
然后:router.push('/')
如何获取路由参数?
const route = useRoute()//获取当前路由参数数组route
8.引入element-plus组件库

这是element ui的升级版,可以用于vue3项目中

安装ElementPlus
  • 安装命令:pnpm add element-plus
安装插件unplugin-vue-componentsunplugin-auto-import实现自动导入
  • 安装命令:npm install -D unplugin-vue-components unplugin-auto-import
  • vite.config.,js中粘贴配置代码如下
import { fileURLToPath, URL } from 'node:url'

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueDevTools from 'vite-plugin-vue-devtools'

import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'

// https://vite.dev/config/
export default defineConfig({
  plugins: [
    vue(),
    vueDevTools(),
    AutoImport({
      resolvers: [ElementPlusResolver()]
    }),
    Components({
      resolvers: [ElementPlusResolver()]
    })
  ],
  resolve: {
    alias: {
      '@': fileURLToPath(new URL('./src', import.meta.url))
    },
  },
})
  • 然后重启项目即可:pnpm dev
  • 效果:可以在项目的任意位置使用element-plus的组件,不需要import,直接用:<el-button type="primary">Primary</el-button>
9.使用Pinia构建一个仓库并实现持久化

Pinia是Vuex的替代,在多组件共享数据的使用场景中用到,区别是取消了mutations和modules

9.1.创建一个用户仓库store/user.js
  • 由于创建项目时选择了pinia,因此在main.js中自动配置好了,可以直接使用
//main.js
import {createPinia} from "pinia"
app.use(createPinia)
  • 新建store/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) => {
    token.value = newToken
  }
  const removeToken = () => {
    token.value = null
  }
  return {
    token,
    setToken,
    removeToken
  }
})
  • 在页面中调用
<script setup>
// 按需导入
import { useUserStore } from './stores/user';
// 调用,拿到仓库对象
const useStore=useUserStore();
</script>

<template>
    <router-view></router-view>
  <div>
    <h3>{{useStore.token}}</h3>
    <el-button @click='useStore.setToken("HELLO VUE3")'>登录</el-button>
    <el-button @click='useStore.removeToken()' >退出</el-button>
  </div>

</template>

此时数据,还不是持久化的,需要进一步优化

9.2.持久化处理
  • 安装插件:`pnpm add pinia-plugin-persistedstate -D
  • `在main.js中导入
import persist from 'pinia-plugin-persistedstate'

app.use(createPinia().use(persist))
  • 配置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) => {
    token.value = newToken
  }
  const removeToken = () => {
    token.value = null
  }
  return {
    token,
    setToken,
    removeToken
  }
}, {//第三个参数
  persist: true
})
  • 效果:

在这里插入图片描述

9.3.pinia代码的统一管理
  • 新建stores/index.js并把main.js中pinia相关代码提取出来
//stores/index.js
import { createPinia } from 'pinia'
import persist from 'pinia-plugin-persistedstate'

const pinia = createPinia()
pinia.use(persist)
export default pinia


//main.js
import { createApp } from 'vue'

import App from './App.vue'
import router from './router'
import pinia from '@/stores/index'

const app = createApp(App)

app.use(router)
app.use(pinia)
app.mount('#app')
  • 配置仓库的统一导入
//假设App.vue导入并使用了两个子模块
import {useUserStore} from "@/stores/modules/user"
import {useCounterStore} from "@/stores/modules/counter"
const useStore=useUserStore()
const countStore=useCounterStore()

/*如何实现仓库统一导出?
最终目的是写成import {useUserStore,useCounterStore} from "@/stores"
做法:用store/index.js作为唯一出口*/

//store/index.js
import { useUserStore } from './user'
export { useUserStore }
import { useCounterStore } from './counter'
export { useCounterStore }

//把上面的按需导入和导出优化如下:(导入直接不用写了)
export * from "./user"
export * from "./counter"
  • 实现仓库的统一导出后的配置和调用代码如下:
//App.vue
import {useUserStore,useCounterStore} from "@/stores"//不用分开按需导入了
const useStore=useUserStore()
const countStore=useCounterStore()

  <div>
    <h3>{{useStore.token}}</h3>
    <h3>{{countStore.count}}</h3>
    <el-button @click='useStore.setToken("HELLO VUE3")'>登录</el-button>
    <el-button @click='useStore.removeToken()' >退出</el-button>
    <el-button @click='countStore.addCount()' >点击</el-button>
  </div>

//store/index.js
export * from "./user"
export * from "./counter"
10.请求工具的设计(vue-router4风格)

把创建axios实例和请求拦截器,响应拦截器放在一个文件中(request.js),并配置基地址,超时时间和携带token和业务失败处理,获取核心响应数据,401处理

  • 安装axios:pnpm add axios
  • 新建utils/request.js,并复制官网代码然后配置如下:
import { useUserStore } from '@/stores/user'
import axios from 'axios'
import router from '@/router'
import { ElMessage } from 'element-plus'
//1.配置基地址
const baseURL = 'http://big-event-vue-api-t.itheima.net'

const instance = axios.create({
  baseURL,
  timeout: 100000
})
// 请求拦截器:发送请求之前做些什么
instance.interceptors.request.use(
  (config) => {
    const userStore = useUserStore()
    if (userStore.token) {//2.配置token
      config.headers.Authorization = userStore.token
    }
    return config
  },
  (err) => Promise.reject(err)
)
// 响应拦截器:接收返回数据之前做些什么
instance.interceptors.response.use(
  (res) => {
    if (res.data.code === 0) {//4.获取核心响应数据
      return res
    }
    //3.处理业务失败:给出错误提示并抛出错误
    ElMessage({ message: res.data.message || '服务异常', type: 'error' })
    return Promise.reject(res.data)
  },
  (err) => {
    ElMessage({ message: err.response.data.message || '服务异常', type: 'error' })
    console.log(err)
    //5.错误的特殊情况:处理401错误(权限不足,token过期==>拦截)
    if (err.response?.status === 401) {
      router.push('/login')
    }
    return Promise.reject(err)
  }
)

export default instance// 导出实例
export { baseURL }//导出基地址

二.创建路由文件和配置路由规则

项目主要由2个一级路由页面:

  • 首页LayoutContainer
  • 注册登录页LoginPage

组成,其中,首页里面嵌套了5个二级路由页面:

  • 频道管理ActicleChannel
  • 文章管理ArticleManage
  • 个人详情UserProfile
  • 更换头像UserAvatar
  • 重置密码UserPassword
创建路由文件

在这里插入图片描述

配置路由规则
//router/index.js
//把首页下的文章管理页http://localhost:5173/article/manage设置为真正的首页
import { createRouter, createWebHistory } from 'vue-router'

const router = createRouter({
  history: createWebHistory(import.meta.env.BASE_URL),
  routes: [
    {
      path: '/',
      component: () => import('../views/layout/LayoutContainer.vue'),
      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: '/',
        redirect: '/article/manage',
      }
      ]
    },
    {
      path: '/login',
      name: 'login',
      component: () => import('../views/login/LoginPage.vue')
    }
  ]
})

export default router

*需要在App.vue和LayoutContainer.vue中写入<router-view></router-view>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

前端OnTheRun

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值