一、项目整体结构概览

Vue 3 项目根目录
配置文件层
源代码层
资源文件层
构建输出层
package.json
vite.config.js
.gitignore
.env 文件
src 目录
main.js 入口
App.vue 根组件
组件目录
其他功能目录
public 静态资源
index.html
dist 构建输出
node_modules

二、完整项目结构树

my-vue3-project/
│
├── 📁 node_modules/          # 项目依赖包(自动生成)
│
├── 📁 public/                # 静态资源目录
│   ├── 📄 favicon.ico       # 网站图标
│   └── 📄 robots.txt        # 搜索引擎配置
│
├── 📁 src/                   # 源代码目录
│   ├── 📁 assets/           # 资源文件
│   │   ├── 📁 images/       # 图片资源
│   │   ├── 📁 styles/       # 样式文件
│   │   └── 📁 fonts/        # 字体文件
│   │
│   ├── 📁 components/       # 公共组件
│   │   ├── 📁 common/       # 通用组件
│   │   └── 📁 layout/       # 布局组件
│   │
│   ├── 📁 views/            # 页面组件
│   │   ├── 📄 Home.vue      # 首页
│   │   ├── 📄 About.vue     # 关于页
│   │   └── 📄 Login.vue     # 登录页
│   │
│   ├── 📁 router/           # 路由配置
│   │   └── 📄 index.js      # 路由主文件
│   │
│   ├── 📁 store/            # 状态管理(Pinia)
│   │   ├── 📄 index.js      # store 主文件
│   │   └── 📁 modules/      # 模块化 store
│   │
│   ├── 📁 utils/            # 工具函数
│   │   ├── 📄 request.js    # axios 封装
│   │   └── 📄 common.js     # 通用工具
│   │
│   ├── 📁 api/              # API 接口
│   │   ├── 📄 user.js       # 用户相关接口
│   │   └── 📄 product.js    # 产品相关接口
│   │
│   ├── 📄 App.vue           # 根组件
│   └── 📄 main.js           # 应用入口
│
├── 📁 tests/                 # 测试文件
│   ├── 📁 unit/             # 单元测试
│   └── 📁 e2e/              # 端到端测试
│
├── 📄 .env                   # 环境变量
├── 📄 .env.development      # 开发环境变量
├── 📄 .env.production       # 生产环境变量
├── 📄 .gitignore            # Git 忽略文件
├── 📄 index.html            # HTML 模板
├── 📄 package.json          # 项目配置
├── 📄 README.md             # 项目说明
└── 📄 vite.config.js        # Vite 配置

三、核心文件详解

3.1 入口文件 (index.html)

<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8">
    <link rel="icon" href="/favicon.ico">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Vue 3 应用</title>
  </head>
  <body>
    <!-- Vue 应用挂载点 -->
    <div id="app"></div>
    <!-- Vite 会自动注入 main.js -->
    <script type="module" src="/src/main.js"></script>
  </body>
</html>

3.2 应用入口 (main.js)

// main.js - 应用程序的入口文件
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import router from './router'
import App from './App.vue'

// 引入全局样式
import './assets/styles/main.css'

// 创建 Vue 应用实例
const app = createApp(App)

// 使用 Pinia 状态管理
app.use(createPinia())

// 使用路由
app.use(router)

// 全局组件注册示例
// app.component('GlobalComponent', GlobalComponent)

// 全局属性注册示例
// app.config.globalProperties.$http = axios

// 挂载应用到 DOM
app.mount('#app')

3.3 主要目录功能流程

组件加载流程
加载对应 View
路由变化
View 引入 Components
Components 使用 Assets
调用 API/Utils
更新 Store 状态
应用启动流程
加载 main.js
index.html
创建 Vue 应用
注册插件/路由/状态
挂载 App.vue
渲染页面

四、src 目录详细说明

4.1 组件目录结构

components 目录
通用组件
业务组件
布局组件
Button.vue
Input.vue
Modal.vue
UserCard.vue
ProductList.vue
ShoppingCart.vue
Header.vue
Footer.vue
Sidebar.vue
组件示例结构:
<!-- components/common/Button.vue -->
<template>
  <button 
    :class="['btn', `btn-${type}`, { 'btn-disabled': disabled }]"
    :disabled="disabled"
    @click="handleClick"
  >
    <slot></slot>
  </button>
</template>

<script setup>
// 使用 Composition API
import { defineProps, defineEmits } from 'vue'

// 定义属性
const props = defineProps({
  type: {
    type: String,
    default: 'primary',
    validator: (value) => ['primary', 'success', 'warning', 'danger'].includes(value)
  },
  disabled: {
    type: Boolean,
    default: false
  }
})

// 定义事件
const emit = defineEmits(['click'])

// 处理点击
const handleClick = (e) => {
  if (!props.disabled) {
    emit('click', e)
  }
}
</script>

<style scoped>
.btn {
  padding: 8px 16px;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  transition: all 0.3s;
}

.btn-primary {
  background-color: #1890ff;
  color: white;
}

.btn-disabled {
  opacity: 0.6;
  cursor: not-allowed;
}
</style>

4.2 路由配置结构

router/index.js
路由配置
路由定义
路由守卫
路由实例
基础路由
嵌套路由
动态路由
全局前置守卫
全局后置守卫
路由独享守卫
// router/index.js
import { createRouter, createWebHistory } from 'vue-router'
import Layout from '@/components/layout/Layout.vue'

const routes = [
  {
    path: '/',
    component: Layout,
    redirect: '/home',
    children: [
      {
        path: 'home',
        name: 'Home',
        component: () => import('@/views/Home.vue'),
        meta: { title: '首页', icon: 'home' }
      },
      {
        path: 'about',
        name: 'About',
        component: () => import('@/views/About.vue'),
        meta: { title: '关于', icon: 'info' }
      }
    ]
  },
  {
    path: '/login',
    name: 'Login',
    component: () => import('@/views/Login.vue'),
    meta: { title: '登录', hideHeader: true }
  },
  {
    path: '/:pathMatch(.*)*',
    name: 'NotFound',
    component: () => import('@/views/404.vue')
  }
]

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

// 路由守卫
router.beforeEach((to, from, next) => {
  // 设置页面标题
  document.title = to.meta.title || 'Vue 3 App'
  
  // 权限验证逻辑
  const token = localStorage.getItem('token')
  if (to.path !== '/login' && !token) {
    next('/login')
  } else {
    next()
  }
})

export default router

4.3 状态管理 (Pinia)

Store 结构
State 状态
Getters 计算
Actions 操作
响应式数据
派生状态
同步操作
异步操作
组件
使用 Store
读取 State
调用 Actions
获取 Getters
// store/modules/user.js
import { defineStore } from 'pinia'
import { login, getUserInfo } from '@/api/user'

export const useUserStore = defineStore('user', {
  // 状态
  state: () => ({
    token: localStorage.getItem('token') || '',
    userInfo: null,
    permissions: []
  }),
  
  // 计算属性
  getters: {
    isLoggedIn: (state) => !!state.token,
    username: (state) => state.userInfo?.username || '',
    hasPermission: (state) => (permission) => {
      return state.permissions.includes(permission)
    }
  },
  
  // 方法
  actions: {
    // 登录
    async login(loginForm) {
      try {
        const { data } = await login(loginForm)
        this.token = data.token
        localStorage.setItem('token', data.token)
        await this.getUserInfo()
        return { success: true }
      } catch (error) {
        return { success: false, message: error.message }
      }
    },
    
    // 获取用户信息
    async getUserInfo() {
      try {
        const { data } = await getUserInfo()
        this.userInfo = data.userInfo
        this.permissions = data.permissions
      } catch (error) {
        console.error('获取用户信息失败', error)
      }
    },
    
    // 登出
    logout() {
      this.token = ''
      this.userInfo = null
      this.permissions = []
      localStorage.removeItem('token')
    }
  }
})

4.4 API 接口管理

组件 API层 Utils/Request 服务器 调用 API 方法 使用封装的请求 添加请求拦截 发送 HTTP 请求 返回响应 响应拦截处理 返回处理后数据 返回最终结果 组件 API层 Utils/Request 服务器
// utils/request.js
import axios from 'axios'
import { ElMessage } from 'element-plus'

// 创建 axios 实例
const service = axios.create({
  baseURL: import.meta.env.VITE_API_BASE_URL,
  timeout: 15000
})

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

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

export default service
// api/user.js
import request from '@/utils/request'

// 用户登录
export function login(data) {
  return request({
    url: '/user/login',
    method: 'post',
    data
  })
}

// 获取用户信息
export function getUserInfo() {
  return request({
    url: '/user/info',
    method: 'get'
  })
}

// 更新用户信息
export function updateUserInfo(data) {
  return request({
    url: '/user/update',
    method: 'put',
    data
  })
}

五、配置文件详解

5.1 Vite 配置

// vite.config.js
import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

export default defineConfig({
  plugins: [vue()],
  
  resolve: {
    alias: {
      '@': fileURLToPath(new URL('./src', import.meta.url))
    }
  },
  
  server: {
    port: 3000,
    host: true,
    open: true,
    proxy: {
      '/api': {
        target: 'http://localhost:8080',
        changeOrigin: true,
        rewrite: (path) => path.replace(/^\/api/, '')
      }
    }
  },
  
  build: {
    target: 'es2015',
    outDir: 'dist',
    assetsDir: 'assets',
    rollupOptions: {
      output: {
        manualChunks: {
          'vue-vendor': ['vue', 'vue-router', 'pinia'],
          'ui-vendor': ['element-plus']
        }
      }
    }
  }
})

5.2 环境变量配置

环境变量文件
.env 通用配置
.env.development 开发环境
.env.production 生产环境
.env.local 本地配置
所有环境共享
开发时使用
构建时使用
不提交到 Git
# .env
VITE_APP_TITLE=My Vue 3 App

# .env.development
VITE_API_BASE_URL=http://localhost:8080/api
VITE_APP_ENV=development

# .env.production
VITE_API_BASE_URL=https://api.example.com
VITE_APP_ENV=production
Logo

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

更多推荐