Vue3 + TS 企业级工程化项目全套实战(Vue3 + Vite + Pinia + VueRouter + Element Plus)

本文作者:LIO

一、项目背景与技术栈选型

这是一个面向中大型后台管理系统的 Vue3 工程化全套方案。你可以直接用于项目脚手架、面试准备或技术博客。

核心技术栈

  • Vue3(Composition API)
  • Vite
  • TypeScript
  • Pinia(替代 Vuex)
  • Vue Router 4
  • Element Plus
  • Axios 封装
  • ESLint + Prettier + Husky
  • Scss / CSS Variables

推荐目录结构(可直接复制使用)

plaintext 复制代码
src
├── api          # 接口请求统一封装
├── assets       # 图片、样式资源
├── components   # 公共组件
├── config       # 全局常量、环境变量
├── hooks        # 通用 hooks
├── layouts      # 布局组件
├── router       # 路由 + 权限路由
├── store        # Pinia 模块化仓库
├── types        // TS 类型声明
├── utils        // 工具函数
├── views        // 业务页面
├── App.vue
└── main.ts

二、Axios 全局请求封装(生产级)

1. 创建 src/utils/request.ts

ts 复制代码
import axios from 'axios'
import { ElMessage, ElLoading } from 'element-plus'

let loadingInstance: any = null

const request = axios.create({
  baseURL: import.meta.env.VITE_API_BASE_URL,
  timeout: 10000,
})

// 请求拦截器
request.interceptors.request.use(
  (config) => {
    loadingInstance = ElLoading.service({ fullscreen: true })
    const token = localStorage.getItem('token')
    if (token) config.headers.Authorization = `Bearer ${token}`
    return config
  },
  (err) => Promise.reject(err)
)

// 响应拦截器
request.interceptors.response.use(
  (res) => {
    loadingInstance.close()
    return res.data
  },
  (err) => {
    loadingInstance.close()
    ElMessage.error(err.response?.data?.message || '请求失败')
    return Promise.reject(err)
  }
)

export default request

2. API 分层示例(src/api/user.ts)

ts 复制代码
import request from '@/utils/request'

export function getUserInfo() {
  return request.get('/user/info')
}

export function login(data: any) {
  return request.post('/login', data)
}

三、Pinia 仓库模块化设计(src/store/index.ts)

ts 复制代码
import { defineStore } from 'pinia'

export const useUserStore = defineStore('user', {
  state: () => ({
    token: localStorage.getItem('token') || '',
    userInfo: null as any,
  }),

  actions: {
    setToken(token: string) {
      this.token = token
      localStorage.setItem('token', token)
    },

    async fetchUserInfo() {
      const res = await getUserInfo()
      this.userInfo = res.data
    },
  },
})

四、Vue Router + 权限路由

src/router/index.ts

ts 复制代码
import { createRouter, createWebHistory } from 'vue-router'
import { useUserStore } from '@/store/user'

const routes = [
  {
    path: '/',
    component: () => import('@/layouts/MainLayout.vue'),
    meta: { requireAuth: true },
    children: [
      { path: '', component: () => import('@/views/Home.vue') },
      { path: 'user', component: () => import('@/views/User.vue') },
    ],
  },
  { path: '/login', component: () => import('@/views/Login.vue') },
]

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

// 全局路由守卫
router.beforeEach((to, from, next) => {
  const userStore = useUserStore()
  if (to.meta.requireAuth && !userStore.token) {
    next('/login')
  } else {
    next()
  }
})

export default router

五、工程化与打包优化(重点)

  1. 路由懒加载
ts 复制代码
component: () => import('@/views/Home.vue')
  1. 分包策略(vite.config.ts)
ts 复制代码
export default defineConfig({
  build: {
    rollupOptions: {
      output: {
        chunkFileNames: 'js/[name]-[hash].js',
        entryFileNames: 'js/[name]-[hash].js',
        assetFileNames: '[ext]/[name]-[hash].[ext]',
      },
    },
  },
})
  1. ESLint + Prettier
plaintext 复制代码
npx eslint --fix .
  1. Husky 提交校验
plaintext 复制代码
npx husky install
npx husky add .husky/pre-commit "npm lint"

六、常见业务场景落地(可直接复制)

1. 分页列表

vue 复制代码
<template>
  <el-table
    :data="list"
    :loading="loading"
  >
    <!-- 列 -->
  </el-table>
  <el-pagination
    v-model:page-size="pageSize"
    v-model:current-page="pageNum"
    :total="total"
    @change="fetchList"
  />
</template>

2. 表单校验

ts 复制代码
const ruleRef = ref()

const rules = {
  name: [{ required: true, message: '请输入名称', trigger: 'blur' }],
}

七、面试高频考点(掘金博客可直接写)

  • Vue3 响应式原理(Proxy)
  • Composition API 与 Options API 区别
  • Pinia 与 Vuex 的差异
  • Vue Router 动态路由实现
  • Vite 与 Webpack 对比
  • 组件懒加载、代码分割
  • 前端鉴权方案(JWT + 路由守卫)

------个人观点 · 仅供参考------

相关推荐
乘风gg30 分钟前
还在养虾吗?虾王已诞生:微信龙虾 ClawBot
前端·ai编程·claude
小小小小宇1 小时前
LLM 长期记忆构建
前端
lichenyang4531 小时前
从 Express 老项目到 NestJS + Docker:一次车辆管理系统的渐进式重构
前端
Momo__2 小时前
VueUse createReusableTemplate —— 单文件组件内的模板复用神器
前端·vue.js
程序员小富2 小时前
我开源了一个开发者专属的智能 JSON 工具,得到了媳妇高度认可
前端·vue.js·后端
小小小小宇2 小时前
程序员如何给 LLM 装工具以及看懂推理过程
前端
写代码的皮筏艇2 小时前
React中的forwardRef
前端·react.js·面试
槑有老呆2 小时前
花三个月工资请了个 AI 程序员,结果它连青岛啤酒股价都查不了
前端
风骏时光牛马2 小时前
Verilog开发常见问题汇总解析
前端
子兮曰3 小时前
AI Coding Method Map:一张图看懂 AI 编程的完整链路
前端·人工智能·后端