最近有个新的项目,基于  Vue3 + Vite + JavaScript + Pinia + Axios + ElementPlus 搭建自动化项目。

1. 项目初始化

步骤 1:创建项目

npm create vite@latest my-vue-app -- --template vue
cd my-vue-app
npm install

打开 PowerShell 进行构建项目:

项目框架初步创建成功,下面是进行二次的封装。

步骤 2:安装依赖

# 安装 Element Plus
npm install element-plus --save

# 安装 Element Plus 图标
npm install @element-plus/icons-vue

# 安装 Less
npm install less --save-dev

# 安装路由和状态管理(可选)
npm install vue-router@4 pinia

2. 项目结构

src
├── .husky/                    # Git Hooks 配置
├── public/                    # 静态资源
├── src/
│   ├── api/                   # API 接口
│   ├── assets/                # 资源文件
│   ├── components/            # 公共组件
│   ├── layout/                # 布局组件
│   ├── router/                # 路由配置
│   ├── store/                 # 状态管理
│   ├── utils/                 # 工具函数
│   ├── views/                 # 页面组件
│   ├── App.vue                # 根组件
│   └── main.js                # 入口文件
├── .eslintrc.js               # ESLint 配置
├── .prettierrc                # Prettier 配置
├── commitlint.config.js       # Commitlint 配置
├── vite.config.js             # Vite 配置
└── package.json

3. 核心配置文件

main.js

import { createApp } from 'vue'
import App from './App.vue'
import router from './router/index'
import { createPinia } from 'pinia'
import './styles/index.less'

// Element Plus
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import * as ElementPlusIconsVue from '@element-plus/icons-vue'



const app = createApp(App)
const pinia = createPinia();

// 注册 Pinia
app.use(pinia);
// 注册路由
app.use(router)
app.use(ElementPlus,{
  locale: zhCn,
}) // 使用 Element Plus

// 注册所有图标
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
  app.component(key, component)
}


app.mount('#app')

vite.config.js

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { resolve } from 'path'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()],
  resolve: {
    alias: {
      '@': resolve(__dirname, 'src')
    }
  },
  server: {
    port: 3000,
    open: true,
    proxy: {
      '/api': {
        target: 'http://localhost:8080',
        changeOrigin: true,
        rewrite: (path) => path.replace(/^\/api/, '')
      }
    }
  },
  css: {
    preprocessorOptions: {
      less: {
        javascriptEnabled: true,
        additionalData: `@import "@/styles/variables.less";`
      }
    }
  }
})

4. 路由配置

router/index.js

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

const routes = [
  {
    path: '/',
    name: 'Home',
    component: () => import('@/views/Home.vue'),
    meta: {
      title: '首页'
    }
  },
  {
    path: '/about',
    name: 'About',
    component: () => import('@/views/About.vue'),
    meta: {
      title: '关于我们'
    }
  }
]

const router = createRouter({
  history: createWebHistory(),
  routes
})

// 路由守卫
router.beforeEach((to, from, next) => {
  if (to.meta.title) {
    document.title = to.meta.title
  }
  next()
})

export default router

5. 状态管理

store/user.js

根据自己的业务进行编写

6. 样式配置

styles/variables.less

根据自己的业务进行编写

styles/index.less

根据自己的业务进行编写

7. 工具函数

utils/request.js

import axios from 'axios'
import { ElMessage } from 'element-plus'
import { useUserStore } from '@/store/user'

// 创建axios实例
const service = axios.create({
  baseURL: '/api',
  timeout: 10000
})

// 请求拦截器
service.interceptors.request.use(
  config => {
    const userStore = useUserStore()
    if (userStore.token) {
      config.headers['Authorization'] = `Bearer ${userStore.token}`
    }
    return config
  },
  error => {
    return Promise.reject(error)
  }
)

// 响应拦截器
service.interceptors.response.use(
  response => {
    const res = response.data
    
    if (res.code !== 200) {
      ElMessage.error(res.message || 'Error')
      return Promise.reject(new Error(res.message || 'Error'))
    } else {
      return res
    }
  },
  error => {
    ElMessage.error(error.message || '请求失败')
    return Promise.reject(error)
  }
)

export default service

8. 环境变量配置

.env.development

VITE_APP_BASE_API=/api
VITE_APP_TITLE=Vue Admin Dev

.env.production

VITE_APP_BASE_API=https://api.example.com
VITE_APP_TITLE=Vue Admin

9. 配置 ESLint 和 Prettier

.eslintrc.cjs

module.exports = {
  root: true,
  env: {
    browser: true,
    es2021: true,
    node: true
  },
  extends: [
    'eslint:recommended', // 推荐的Vue规则
    'plugin:vue/vue3-essential',
    '@typescript-eslint/recommended', // 更严格的Vue规则
    'prettier' // 解决ESLint与Prettier的冲突
  ],
  parserOptions: {
    ecmaVersion: 'latest',
    sourceType: 'module',
    parser: '@babel/eslint-parser'
  },
  plugins: ['prettier'],
  rules: {
    // Vue 相关规则
    'vue/multi-word-component-names': 'off', // 允许单文件组件名
    'vue/html-self-closing': [
      'error',
      {
        html: { void: 'always' }
      }
    ],

    // JavaScript 通用规则
    'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
    'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
    'prefer-const': 'error',
    'no-unused-vars': 'warn',

    // Prettier 集成
    'prettier/prettier': [
      'error',
      {
        endOfLine: 'auto',
        singleQuote: true,
        semi: false,
        trailingComma: 'none'
      }
    ]
  }
}

.prettierrc

{
  "printWidth": 100, // 每行代码最大长度
  "tabWidth": 2, // 缩进空格数
  "useTabs": false, // 使用空格而非制表符
  "semi": true, // 语句结尾添加分号
  "singleQuote": true, // 使用单引号
  "quoteProps": "as-needed", // 仅在需要时为对象属性添加引号
  "trailingComma": "es6", // 为ES6中的对象、数组等添加 trailing comma
  "bracketSpacing": true, // 对象字面量的大括号间使用空格
  "arrowParens": "always", // 箭头函数的参数始终使用括号
  "htmlWhitespaceSensitivity": "ignore", // HTML空白敏感度
  "vueIndentScriptAndStyle": true, // Vue文件中脚本和样式标签的缩进
  "endOfLine": "lf" // 行尾换行符
}

10. Husky 配置

package.json 脚本

{
  "name": "secret_pigeon_web",
  "private": true,
  "version": "0.0.0",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "preview": "vite preview"
  },
  "dependencies": {
    "@element-plus/icons-vue": "^2.3.2",
    "element-plus": "^2.11.4",
    "pinia": "^3.0.3",
    "vue": "^3.5.22",
    "vue-router": "^4.6.2"
  },
  "devDependencies": {
    "@babel/eslint-parser": "^7.28.4",
    "@vitejs/plugin-vue": "^6.0.1",
    "@vue/eslint-config-prettier": "^10.2.0",
    "eslint": "^9.37.0",
    "eslint-config-prettier": "^10.1.8",
    "eslint-plugin-prettier": "^5.5.4",
    "eslint-plugin-vue": "^10.5.1",
    "less": "^4.4.2",
    "prettier": "^3.6.2",
    "vite": "^7.1.7"
  },
  "lint-staged": {
    "*.{js,jsx,vue}": [
      "eslint --fix",
      "prettier --write"
    ],
    "*.{html,css,less,scss,md}": [
      "prettier --write"
    ]
  }
}

初始化 Husky

# 初始化 Husky
npm run prepare

# 添加 pre-commit hook
npx husky add .husky/pre-commit "npx lint-staged"

# 添加 commit-msg hook
npx husky add .husky/commit-msg 'npx --no-install commitlint --edit "$1"'

Git 提交规范

feat: 新增功能
fix: 修复bug
docs: 文档变更
style: 代码格式
refactor: 代码重构
perf: 性能优化
test: 测试相关
chore: 构建过程或辅助工具变动
revert: 回退提交
build: 打包相关

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐