使用Vue3+Vite+Pinia+elementUI搭建初级企业级项目

本项目的技术栈 本项目技术栈基于ES6vue3piniavue-routervite 、axios 和 element-plus

本项目仅介绍搭建项目的过程,以及对插件的基础配置

一、目标

搭建一个基础版的企业级项目,最开始的项目搭建,项目代码管理使用的是Git,所完成以下基本内容:

  1. pnpm 包管理升级
  2. Eslint + prettier 规范设置
  3. husky (Git hooks工具)代码提交之前检查
  4. Vue3 composition API
  5. VueRouter4 路由代码解析
  6. 引入 element-ui 组件库
  7. Pinia / Pinia 持久化处理
  8. axios 请求模块设计

二、pnpm 包管理器 - 创建项目

一些优势:比同类工具快 2倍 左右、节省磁盘空间... https://www.pnpm.cn/

  1. 安装方式:

    bash 复制代码
    npm install -g pnpm
  2. 创建项目:

    bash 复制代码
    pnpm create vue

    项目创建使用到了四个功能(Router、Pinia、Linter、Prettier)

命令对比:

三、ESLint & prettier 配置代码风格

环境同步:

  1. 安装了插件 ESlint,开启保存自动修复
  2. 禁用了插件 Prettier,并关闭保存自动格式化
json 复制代码
// ESlint插件 + Vscode配置 实现自动格式化修复
"editor.codeActionsOnSave": {
    "source.fixAll": "explicit" // true
},
"editor.formatOnSave": false,

配置文件 .eslintrc.cjs / eslint.config.js

  1. prettier 风格配置 https://prettier.io
    (1) 单引号
    (2) 不使用分号
    (3) 每行宽度至多80字符
    (4) 不加对象|数组最后逗号
    (5) 换行符号不限制(win mac 不一致)
  2. vue组件名称多单词组成(忽略index.vue)
  3. props解构(关闭)
javascript 复制代码
  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'
  }

四、基于 husky 的代码检查工作流

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

1、husky 配置

  1. git初始化 git init

  2. 初始化 husky 工具配置 https://typicode.github.io/husky/
    注意: 在vscode中,终端切换成 Git Bash

    bash 复制代码
    pnpm dlx husky-init && pnpm install
  3. 修改 .husky/pre-commit 文件,由 npm test 改为 pnpm lint

    bash 复制代码
    pnpm lint

2、lint-staged 配置

  1. 安装

    bash 复制代码
    pnpm i lint-staged -D
  2. 配置 package.json

    json 复制代码
    // lint-staged 与 scripts、devDependencies 等配置平级放置,放在最下面即可
    {
      // ... 省略 ...
      "lint-staged": {
        "*.{js,ts,vue}": [
          "eslint --fix"
        ]
      }
    }
    
    // 配置 scripts
    {
      "scripts": {
        // ... 省略 ...
        "lint-staged": "lint-staged"
      }
    }
  3. 修改 .husky/pre-commit 文件

    bash 复制代码
    pnpm lint-staged

3、pnpm lint 与 pnpm lint-staged 区别

在 .husky/pre-commit 文件中,配置 pnpm lintpnpm lint-staged

  • pnpm lint:全量检查,耗时问题,历史问题
    默认执行全量检查,每次提交都需完整扫描,耗时较长。此外,若存在历史遗留问题,必须全部修复后才能提交。
  • pnpm lint-staged:仅检查当前修改部分
    提交修改时仅检查当前内容,处理迅速,不追溯历史问题。

建议:

  1. 当多人维护一个项目时,使用 lint-staged 确保自己提交的代码正确性
  2. 有余力时,切换至 lint 处理历史遗留问题

五、调整项目目录

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

  • 删除初始化的默认文件

  • 修改剩余代码内容

  • 新增调整我们需要的目录结构

  • 拷贝初始化资源文件,安装预处理器插件

  1. 删除文件

  2. 修改内容
    src/router/index.js

    javascript 复制代码
    import { createRouter, createWebHistory } from 'vue-router'
    
    const router = createRouter({
      history: createWebHistory(import.meta.env.BASE_URL),
      routes: []
    })
    
    export default router

    src/App.vue

    xml 复制代码
    <script setup></script>
    
    <template>
      <div>
        <router-view></router-view>
      </div>
    </template>
    
    <style scoped></style>

    src/main.js

    javascript 复制代码
    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')
  3. 目录结构

  4. 将项目需要的全局样式 和 图片文件,复制到 assets 文件夹中, 并将全局样式在main.js中引入

    js 复制代码
    import '@/assets/main.scss'
  5. 安装 sass 依赖

    bash 复制代码
    pnpm add sass -D

六、VueRouter4 路由代码解析

基础代码解析

js 复制代码
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

import.meta.env.BASE_URL 是Vite 环境变量:https://cn.vitejs.dev/guide/env-and-mode.html

七、引入 element-ui 组件库

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

  • 安装

    bash 复制代码
    $ pnpm add element-plus

自动按需:

  1. 安装插件

    bash 复制代码
    pnpm add -D unplugin-vue-components unplugin-auto-import
  2. 然后把下列代码插入到你的 ViteWebpack 的配置文件中

    javascript 复制代码
    ...
    import AutoImport from 'unplugin-auto-import/vite'
    import Components from 'unplugin-vue-components/vite'
    import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
    
    // https://vitejs.dev/config/
    export default defineConfig({
      plugins: [
        ...
        AutoImport({
          resolvers: [ElementPlusResolver()]
        }),
        Components({
          resolvers: [ElementPlusResolver()]
        })
      ]
    })
  3. 直接使用

    xml 复制代码
    <template>
      <div>
        <el-button type="primary">Primary</el-button>
        <el-button type="success">Success</el-button>
        <el-button type="info">Info</el-button>
        <el-button type="warning">Warning</el-button>
        <el-button type="danger">Danger</el-button>
        ...
      </div>
    </template>

八、Pinia - 构建用户仓库 和 持久化

官方文档:https://prazdevs.github.io/pinia-plugin-persistedstate/zh/

  1. 安装插件 pinia-plugin-persistedstate

    bash 复制代码
    pnpm add pinia-plugin-persistedstate -D
  2. 使用 main.js

    javascript 复制代码
    import persist from 'pinia-plugin-persistedstate'
    ...
    app.use(createPinia().use(persist))
  3. 配置 stores/user.js

    javascript 复制代码
    import { defineStore } from 'pinia'
    import { ref } from 'vue'
    
    // 用户模块
    export const useUserStore = defineStore(
      'big-user',
      () => {
        const token = ref('') // 定义 token
        const setToken = (t) => (token.value = t) // 设置 token
    
        return { token, setToken }
      },
      {
        persist: true // 持久化
      }
    )

九、Pinia - 配置仓库统一管理

  1. pinia 独立维护

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

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

  2. 仓库 统一导出

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

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

十、数据交互 - 请求工具设计

1. 创建 axios 实例

们会使用 axios 来请求后端接口, 一般都会对 axios 进行一些配置 (比如: 配置基础地址等)

一般项目开发中, 都会对 axios 进行基本的二次封装, 单独封装到一个模块中, 便于使用

  1. 安装 axios

    bash 复制代码
    pnpm add axios
  2. 新建 utils/request.js 封装 axios 模块

    利用 axios.create 创建一个自定义的 axios 来使用

    http://www.axios-js.com/zh-cn/docs/#axios-create-config

    javascript 复制代码
    import 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. 携带token
        return 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

2. 完成 axios 基本配置

javascript 复制代码
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'

const instance = axios.create({
  baseURL,
  timeout: 100000
})

instance.interceptors.request.use(
  (config) => {
    const userStore = useUserStore()
    if (userStore.token) {
      config.headers.Authorization = userStore.token
    }
    return config
  },
  (err) => Promise.reject(err)
)

instance.interceptors.response.use(
  (res) => {
    if (res.data.code === 0) {
      return res
    }
    ElMessage({ message: res.data.message || '服务异常', type: 'error' })
    return Promise.reject(res.data)
  },
  (err) => {
    ElMessage({ message: err.response.data.message || '服务异常', type: 'error' })
    console.log(err)
    if (err.response?.status === 401) {
      router.push('/login')
    }
    return Promise.reject(err)
  }
)

export default instance
export { baseURL }
相关推荐
菜鸟una1 小时前
【微信小程序+Taro 3+NutUI 3】input (nut-input) 、 textarea (nut-texteare)类型使用避坑
前端·vue.js·微信小程序·小程序·taro
Highcharts.js2 小时前
如何在构建音频图表中映射到数据?
javascript·信息可视化·音视频·开发文档·highcharts·数据映射
Jiaberrr2 小时前
小程序setData性能优化指南:避开坑点,让页面丝滑如飞
前端·javascript·vue.js·性能优化·小程序
m0_694845572 小时前
HandBrake 是什么?视频转码工具使用与服务器部署教程
服务器·前端·pdf·开源·github·音视频
方安乐2 小时前
react笔记之tanstack
前端·笔记·react.js
学嵌入式的小杨同学10 小时前
从零打造 Linux 终端 MP3 播放器!用 C 语言实现音乐自由
linux·c语言·开发语言·前端·vscode·ci/cd·vim
weixin_4255437311 小时前
TRAE CN3.3.25 构建的Electron简易DEMO应用
前端·typescript·electron·vite·nestjs
Mr Xu_11 小时前
【Vue3 + ECharts 实战】正确使用 showLoading、resize 与 dispose 避免内存泄漏
前端·信息可视化·vue·echarts
0思必得012 小时前
[Web自动化] Selenium设置相关执行文件路径
前端·爬虫·python·selenium·自动化