引言:在前端开发领域,Vue.js凭借其轻量、易用、渐进式的特性,成为众多开发者构建单页应用(SPA)的首选框架。无论是个人项目还是企业级应用,一套规范的设计思路和搭建流程,都能极大提升开发效率、降低后期维护成本。本文将带你从项目设计理念出发,一步步完成Vue项目的搭建与基础配置,助力你快速上手Vue项目开发。

一、项目设计前期:明确核心需求与技术选型

在动手搭建项目前,切勿急于敲代码,先做好前期规划是项目成功的关键。这一阶段主要需要明确两个核心问题:需求边界和技术栈选型。

1. 需求梳理与架构设计

首先要清晰梳理项目的核心功能的功能,比如是后台管理系统、移动端H5、还是PC端官网?不同的场景对技术的要求不同。例如,后台管理系统更注重权限控制、数据表格、表单验证等功能;移动端H5则需要考虑适配、性能优化、手势交互等问题。

其次,进行简单的架构设计:确定项目的目录结构规范、状态管理方案、路由设计、接口请求方案等。建议采用模块化、组件化的设计思想,将项目拆分为多个独立的功能模块,便于后期维护和功能扩展。

2. 技术栈选型

基于Vue生态,结合项目需求选择合适的技术栈:

  • 核心框架:Vue 3(推荐,支持Composition API、更好的TypeScript支持、性能更优)

  • 构建工具:Vite(替代Webpack,启动速度更快、热更新更高效)

  • 路由管理:Vue Router(Vue官方路由插件,处理页面跳转、路由守卫等)

  • 状态管理:Pinia(Vue官方推荐,替代Vuex,API更简洁、支持TypeScript、无需嵌套模块)

  • UI组件库:根据场景选择,比如Element Plus(PC端后台管理)、Vant(移动端)、Ant Design Vue(企业级应用)

  • HTTP请求:Axios(处理接口请求、拦截器、请求响应封装)

  • 类型检查:TypeScript(增强代码可读性、减少运行时错误)

  • 样式解决方案:Scss/Sass(CSS预处理器,支持变量、混合、嵌套等)、CSS Modules(避免样式冲突)

  • 代码规范:ESLint(代码语法检查)、Prettier(代码格式化)

二、项目搭建:从环境准备到基础初始化

本章节以“Vue 3 + Vite + TypeScript + Pinia + Axios + Element Plus”技术栈为例,详细讲解项目的搭建过程。

1. 环境准备

首先确保本地安装了Node.js和npm/yarn/pnpm(推荐使用pnpm,速度更快、占用空间更小):

  • Node.js:版本需≥14.18.0(Vite的最低要求),可通过Node.js官网下载安装

  • pnpm:安装命令:npm install -g pnpm

验证安装成功:


node -v # 输出Node.js版本号 pnpm -v # 输出pnpm版本号

2. 初始化Vite + Vue项目

使用Vite官方脚手架初始化项目,执行以下命令:


pnpm create vite@latest vue-project-demo --template vue-ts

命令说明:

  • create vite@latest:创建最新版本的Vite项目

  • vue-project-demo:项目名称(可自定义)

  • --template vue-ts:指定模板为Vue + TypeScript

执行命令后,根据提示完成项目创建,然后进入项目目录并安装依赖:


cd vue-project-demo # 进入项目目录 pnpm install # 安装项目依赖

启动项目:


pnpm dev

启动成功后,访问终端提示的地址(默认是http://127.0.0.1:5173/),即可看到Vite + Vue的默认页面。

3. 项目目录结构优化

Vite初始化后的目录结构比较简单,我们需要根据项目规范进行优化,使其更符合模块化开发需求。优化后的目录结构如下:

Vue 项目目录结构详解

以下是一个标准 Vue 3 + Vite + TypeScript 项目的目录结构说明,适用于中大型项目开发。

public/

存放静态资源文件,这些文件不会被 Vite 处理,会直接复制到打包目录。通常放置:

  • favicon.ico
  • robots.txt
  • 其他不需要构建处理的静态文件
src/

项目核心代码目录,包含所有源代码文件。

src/api/

接口请求相关封装:

  • 按模块划分接口定义文件
  • 统一封装 axios 实例
  • 请求拦截和响应拦截配置
src/assets/

会被 Vite 处理的静态资源:

  • icons/ 存放 SVG 图标或字体图标
  • images/ 存放项目图片资源
  • styles/ 包含全局样式文件:
    • reset.scss 重置样式
    • variables.scss SCSS 变量定义
    • mixins.scss SCSS 混入
    • global.scss 全局样式
src/components/

公共组件目录,建议分为:

  • base/ 基础 UI 组件(按钮、输入框等)
  • business/ 业务相关组件(与具体功能相关)
  • 组件命名采用 PascalCase 风格
src/composables/

存放 Composition API 的可复用逻辑:

  • useFetch.ts 数据请求封装
  • useForm.ts 表单处理逻辑
  • usePagination.ts 分页逻辑
src/layouts/

布局组件,适用于多布局场景:

  • DefaultLayout.vue 默认布局
  • AdminLayout.vue 后台管理布局
  • AuthLayout.vue 认证相关页面布局
src/router/

路由配置:

  • index.ts 路由定义
  • routes.ts 路由表
  • guard.ts 路由守卫逻辑
src/stores/

Pinia 状态管理:

  • user.ts 用户相关状态
  • app.ts 应用全局状态
  • modules/ 按模块划分的状态
src/types/

TypeScript 类型定义:

  • api.d.ts 接口返回类型
  • global.d.ts 全局类型扩展
  • 按模块划分的类型文件
src/utils/

工具函数集合:

  • auth.ts 权限相关
  • request.ts 请求工具
  • date.ts 日期处理
  • validate.ts 验证工具
src/views/

页面级组件,与路由对应:

  • 按功能模块划分子目录
  • 每个页面目录可包含组件和资源
  • 命名与路由路径保持一致
配置文件
  • .eslintrc.cjs ESLint 配置
  • .prettierrc.cjs 代码格式化配置
  • tsconfig.json TypeScript 编译配置
  • vite.config.ts Vite 构建配置

最佳实践建议

  1. 组件命名统一使用 PascalCase
  2. 类型定义使用 TypeScript 接口
  3. 状态管理优先使用 Pinia
  4. API 请求统一封装和错误处理
  5. 样式使用 SCSS 并遵循 BEM 规范
  6. 路由使用懒加载提升性能
  7. 工具函数做好单元测试

三、核心配置:打造规范、高效的开发环境

项目搭建完成后,需要进行一系列核心配置,包括Vite配置、路由配置、Pinia状态管理配置、Axios请求封装、UI组件库引入等,为后续开发奠定基础。

1. Vite配置优化(vite.config.ts)

Vite的默认配置可能无法满足项目需求,我们需要对其进行扩展,比如配置别名、跨域代理、全局样式、插件等。示例配置如下:

配置解析

这段代码是Vite项目的配置文件,主要包含插件配置、路径别名、开发服务器代理和CSS预处理器的设置。

插件配置

plugins: [vue()]

使用Vue官方插件支持Vue单文件组件,这是Vite项目中使用Vue的必要配置。

路径别名

resolve: {
  alias: {
    '@': path.resolve(__dirname, './src')
  }
}

配置了路径别名,将@映射到项目根目录下的src目录,方便在项目中通过@/形式引用src目录下的文件。

开发服务器配置

server: {
  port: 5173,
  open: true,
  proxy: {
    '/api': {
      target: 'http://localhost:3000',
      changeOrigin: true,
      rewrite: (path) => path.replace(/^\/api/, '')
    }
  }
}

设置开发服务器的端口为5173,启动后自动打开浏览器。配置了API代理,将以/api开头的请求转发到http://localhost:3000,并去掉/api前缀,用于解决开发环境下的跨域问题。

CSS配置

css: {
  preprocessorOptions: {
    scss: {
      additionalData: '@import "@/assets/styles/variables.scss";'
    }
  }
}

配置SCSS预处理器,全局引入variables.scss文件,使得所有SCSS文件都能使用其中定义的变量,无需单独导入。

使用建议

在项目中使用路径别名时,确保TypeScript也能识别这些别名,需要在tsconfig.json中添加相应配置:

{
  "compilerOptions": {
    "paths": {
      "@/*": ["src/*"]
    }
  }
}

注意事项

开发服务器代理配置只在开发环境下生效,生产环境需要确保API请求路径正确或配置相应的反向代理。全局SCSS变量文件需要确保路径正确,避免因路径错误导致编译失败。

2. 路由配置(src/router/index.ts)

使用Vue Router配置项目路由,包括路由规则、路由守卫(如登录验证)等。首先安装Vue Router:pnpm install vue-router@4 # Vue 3对应Vue Router 4版本

然后创建路由配置文件:

以下是对Vue Router配置代码的分析和优化建议,适用于基于Vue 3和Pinia的状态管理方案:

路由配置优化

路由规则采用TypeScript类型标注RouteRecordRaw,确保类型安全。布局组件与页面组件分离,通过children属性实现嵌套路由结构。meta字段用于扩展路由元信息,如requiresAuth标记鉴权需求。

路由守卫增强

在全局前置守卫beforeEach中,通过Pinia的useUserStore获取用户状态。当目标路由需要认证(requiresAuth)且未检测到token时,重定向到登录页。否则正常放行路由跳转。

// 建议添加白名单路径常量
const WHITE_LIST = ['/login']
router.beforeEach((to) => {
  const userStore = useUserStore()
  if (userStore.token) {
    if (to.path === '/login') {
      return '/' // 已登录时访问登录页自动跳转首页
    }
  } else if (!WHITE_LIST.includes(to.path)) {
    return { path: '/login', query: { redirect: to.fullPath } } // 记录重定向路径
  }
})

动态路由扩展

对于权限管理系统,可补充动态路由加载逻辑。在用户登录后根据权限数据添加可访问路由:

// 在登录成功后调用
function setupDynamicRoutes() {
  const routes = generateRoutesByPermission()
  routes.forEach(route => router.addRoute(route))
}

类型安全强化

建议为meta字段定义类型扩展,增强代码提示:

declare module 'vue-router' {
  interface RouteMeta {
    requiresAuth: boolean
    permission?: string[]
  }
}

历史模式选择

当前配置使用HTML5历史模式(createWebHistory),需确保服务器已配置URL回退规则。若需支持静态部署,可考虑哈希模式(createWebHashHistory)。

该配置方案实现了基础路由分层和权限控制,可根据实际项目需求扩展动态路由加载、路由过渡动画等功能模块。

最后在入口文件main.ts中引入路由:

代码解析

这段代码是Vue 3应用的初始化代码,使用了Vue Router和Pinia状态管理库。以下是对代码各部分的详细说明:

导入依赖

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

  • createApp是Vue 3的核心函数,用于创建应用实例
  • App是根组件
  • router是路由配置
  • createPinia用于创建Pinia状态管理实例

创建应用实例

const app = createApp(App)

  • 使用根组件App创建Vue应用实例

使用插件

app.use(createPinia())
app.use(router)

  • 通过app.use()方法注册Pinia和Vue Router
  • Pinia提供全局状态管理
  • Vue Router处理应用路由

挂载应用

app.mount('#app')

  • 将应用挂载到DOM元素#app
  • 这是应用启动的最后一步

常见配置补充

Pinia持久化存储配置示例:

import { createPinia } from 'pinia'
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'

const pinia = createPinia()
pinia.use(piniaPluginPersistedstate)
app.use(pinia)

路由守卫配置示例:

router.beforeEach((to, from, next) => {
  // 路由守卫逻辑
  next()
})

项目结构建议

  • 将状态管理相关代码放在stores/目录
  • 路由配置放在router/index.js
  • 主入口文件保持简洁,只包含核心初始化逻辑

3. Pinia状态管理配置(src/stores/user.ts)

Pinia是Vue 3官方推荐的状态管理工具,使用起来比Vuex更简洁。首先安装Pinia:


pnpm install pinia

然后创建用户模块的Store(示例):


import { defineStore } from 'pinia' import { loginApi } from '@/api/user' // 定义User类型 interface UserState { token: string | null username: string | null roles: string[] } // 创建Store export const useUserStore = defineStore('user', { // 状态 state: (): UserState => ({ token: localStorage.getItem('token'), // 从本地存储获取token username: localStorage.getItem('username'), roles: [] }), // 计算属性 getters: { isLogin: (state) => !!state.token // 判断是否登录 }, // 方法(同步/异步) actions: { // 登录动作 async login(data: { username: string; password: string }) { const res = await loginApi(data) const { token, username, roles } = res.data // 更新状态 this.token = token this.username = username this.roles = roles // 本地存储持久化 localStorage.setItem('token', token) localStorage.setItem('username', username) }, // 退出登录 logout() { this.token = null this.username = null this.roles = [] localStorage.clear() } } })

4. Axios请求封装(src/utils/request.ts)

Axios是处理HTTP请求的常用工具,我们需要对其进行封装,统一处理请求拦截、响应拦截、错误处理等。首先安装Axios:

pnpm install axios

然后创建请求工具文件:

优化Axios封装代码

以下是对现有Axios封装代码的分析和优化建议,提升可维护性和功能性:

代码结构优化 将Axios实例配置、拦截器逻辑拆分为独立模块,便于维护。例如创建src/utils/http.js集中管理HTTP相关配置。

环境变量校验 添加环境变量校验逻辑,确保VITE_API_BASE_URL存在:

if (!import.meta.env.VITE_API_BASE_URL) {
  console.error('Missing API base URL in environment variables')
}

类型增强 为响应数据添加TypeScript类型定义(如使用TS):

interface ApiResponse<T = any> {
  code: number
  data: T
  msg?: string
}

拦截器改进 请求拦截器中添加Content-Type默认设置:

config.headers['Content-Type'] = config.headers['Content-Type'] || 'application/json'

错误处理增强 响应拦截器区分不同错误类型:

if (error.response) {
  // 服务器响应错误
  const status = error.response.status
  const errorMap = {
    400: '请求参数错误',
    403: '没有权限',
    404: '资源不存在',
    500: '服务器内部错误'
  }
  ElMessage.error(errorMap[status] || `服务器错误: ${status}`)
} else if (error.request) {
  // 请求未收到响应
  ElMessage.error('网络连接异常,请检查网络')
} else {
  // 其他错误
  ElMessage.error('请求配置错误')
}

重试机制 对于网络波动导致的失败,添加请求重试逻辑:

const MAX_RETRY = 2
let retryCount = 0

const retryRequest = (config) => {
  return new Promise((resolve) => {
    setTimeout(() => {
      console.log(`Retry attempt ${retryCount + 1}`)
      resolve(service(config))
    }, 1000 * (retryCount + 1))
  })
}

service.interceptors.response.use(null, async (error) => {
  const shouldRetry = error.code === 'ECONNABORTED' && retryCount < MAX_RETRY
  if (shouldRetry) {
    retryCount++
    return retryRequest(error.config)
  }
  return Promise.reject(error)
})

取消请求 集成AbortController支持请求取消:

const controller = new AbortController()

service.get('/api', {
  signal: controller.signal
})

// 需要取消时
controller.abort()

性能监控 添加请求耗时统计:

service.interceptors.request.use((config) => {
  config.metadata = { startTime: new Date() }
  return config
})

service.interceptors.response.use((response) => {
  const endTime = new Date()
  const duration = endTime - response.config.metadata.startTime
  console.log(`请求 ${response.config.url} 耗时 ${duration}ms`)
  return response
})

缓存策略 为GET请求添加简单缓存:

const cacheMap = new Map()

service.interceptors.request.use((config) => {
  if (config.method === 'get') {
    const cacheKey = JSON.stringify(config)
    if (cacheMap.has(cacheKey)) {
      return Promise.resolve(cacheMap.get(cacheKey))
    }
  }
  return config
})

service.interceptors.response.use((response) => {
  if (response.config.method === 'get') {
    const cacheKey = JSON.stringify(response.config)
    cacheMap.set(cacheKey, response)
  }
  return response
})

这些优化方案可根据实际项目需求选择性实施,建议通过配置文件管理超时时间、重试次数等参数,避免硬编码。对于大型项目,考虑使用更完善的状态管理方案处理全局加载状态和错误信息。

然后在api目录下创建接口请求函数(示例:src/api/user.ts):


import request from '@/utils/request' // 登录接口 export const loginApi = (data: { username: string; password: string }) => { return request({ url: '/login', method: 'post', data }) } // 获取用户信息接口 export const getUserInfoApi = () => { return request({ url: '/user/info', method: 'get' }) }

5. UI组件库引入(Element Plus)

以Element Plus为例,介绍UI组件库的引入方式(推荐按需引入,减少打包体积)。首先安装Element Plus:

pnpm install element-plus @element-plus/icons-vue

然后在入口文件main.ts中全局引入样式(按需引入组件需要配合插件):

全局引入Element Plus及其图标的方法

在Vue 3项目中全局引入Element Plus及其图标组件,需要按照以下方式配置:

安装Element Plus和图标库依赖

npm install element-plus @element-plus/icons-vue

在main.js或main.ts中配置全局引入

import { createApp } from 'vue'
import App from './App.vue'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import * as ElementPlusIconsVue from '@element-plus/icons-vue'

const app = createApp(App)

app.use(ElementPlus)

for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
  app.component(key, component)
}

app.mount('#app')

按需引入图标的方法

如果只需要使用部分图标,可以采用按需引入的方式:

import { Menu, Search } from '@element-plus/icons-vue'

const app = createApp(App)
app.component('ElIconMenu', Menu)
app.component('ElIconSearch', Search)

使用图标的注意事项

在模板中使用注册的图标组件时,需要添加el-icon前缀:

<el-icon-menu />
<el-icon-search />

TypeScript支持配置

对于TypeScript项目,需要在tsconfig.json中添加类型声明:

{
  "compilerOptions": {
    "types": ["element-plus/global"]
  }
}

如需按需引入组件,可安装unplugin-vue-components插件,在vite.config.ts中配置,实现组件自动导入,无需手动引入。

四、项目开发规范:提升代码质量与协作效率

良好的开发规范是团队协作的基础,也是保证项目可维护性的关键。以下是一些常用的开发规范建议:

1. 代码规范(ESLint + Prettier)

Vite初始化项目时已自带ESLint配置,我们可以根据项目需求修改.eslintrc.cjs和.prettierrc.cjs文件,统一代码风格。例如:

以下是对该 ESLint 配置文件的详细解析与优化建议:

配置结构说明

root: true 表示该配置文件为项目根配置,ESLint 不会继续向上查找父级目录的配置。

env 定义了代码运行环境:

  • browser: true 启用浏览器全局变量(如 window
  • es2021: true 支持 ES2021 语法特性

扩展规则集

extends 继承的规则组合:

  • eslint:recommended ESLint 官方推荐规则
  • plugin:vue/vue3-essential Vue 3 基础语法规则
  • plugin:@typescript-eslint/recommended TypeScript 推荐规则
  • plugin:prettier/recommended 集成 Prettier 格式化规则

解析器配置

parser: 'vue-eslint-parser' 指定 Vue 单文件解析器,配合 parserOptions.parser: '@typescript-eslint/parser' 实现 TS 语法解析。

自定义规则调整

rules 中的自定义规则覆盖:

'vue/multi-word-component-names': 'off' // 允许单单词组件名(如 Home.vue)
'@typescript-eslint/no-unused-vars': 'warn' // 未使用变量提示警告而非报错
'prettier/prettier': 'error' // 格式化问题直接报错

常见补充配置建议

对于 Vue 3 + TypeScript 项目,可考虑添加:

globals: {
  defineProps: 'readonly',
  defineEmits: 'readonly'
}

性能优化选项

大型项目可添加:

parserOptions: {
  extraFileExtensions: ['.vue'],
  project: './tsconfig.json' // 关联 TS 配置
}

该配置已实现主流工具链集成,适合现代 Vue 3 + TypeScript 项目开发。根据团队规范可调整规则严格级别(error/warn/off)。

2. 组件实例

代码:

<template>

    <div class="page">

         <h1>父组件</h1>

         <p>接受子组件传递过来的数据:{{ msg }}</p>

         <p>****************************************</p>

         <EmitChild @change="getVal"/>

    </div>

</template>

<script>

import EmitChild from '@/components/EmitChild.vue';

export default{

    data(){

        return{

           msg:''

        }

    },

    components:{

    EmitChild

    },

    methods:{

        getVal:function(val){

            this.msg=val

        }

    }

}

</script>

<style scoped></style>

图片:

3. 目录规范

严格按照优化后的目录结构存放文件,避免文件乱放导致后期维护困难。例如:静态资源放在assets目录,工具函数放在utils目录,接口请求放在api目录等。

五、项目打包与部署

项目开发完成后,需要打包生成生产环境的代码,然后部署到服务器。

1. 打包配置

在package.json中已自带打包脚本,执行以下命令打包:


pnpm run build

打包完成后,会生成dist目录,该目录下的文件即为生产环境的静态资源。

2. 部署方式

根据项目需求选择合适的部署方式:

  • 静态服务器部署:将dist目录下的文件上传到Nginx、Apache等静态服务器。

  • 云服务部署:如阿里云OSS、腾讯云COS、Netlify、Vercel等,支持一键部署。

  • 容器化部署:使用Docker打包项目,部署到Docker容器或K8s集群。

以Nginx部署为例,需要配置Nginx的location规则,指向dist目录,并处理SPA的路由问题(避免刷新页面404):


server { listen 80; server_name your-domain.com; # 你的域名 location / { root /path/to/dist; # dist目录的绝对路径 index index.html; try_files $uri $uri/ /index.html; # 处理SPA路由 } }

六、总结与拓展

本文从项目设计前期的需求梳理、技术选型,到项目搭建、核心配置,再到开发规范、打包部署,完整呈现了Vue项目从0到1的搭建流程。掌握这套流程后,你可以快速搭建起​

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐