切换导航
简历
工具
演示
查询
导航菜单
服务端
30
前端
114
数据库
82
进阶开发
8
桌面程序
2
QA
15
软件使用
36
规范协议
5
操作系统
11
AI
0
复用资源
6
硬件
0
外部链接
.NET Core SDK和运行时安装包
淘宝 NPM 镜像
查询网
Tables Generator线上表格转换工具
引用cdn在线脚本和样式
首页
复用资源
vue 3.0 项目目录结构图
[TOC] ## vue 3.0 项目文件目录结构 ```shell src ├── utils │ ├── polyfill.js # 浏览器兼容垫片 │ └── request.js # axios统一请求封装 ├── mock │ ├── index.js # mock总入口、开关控制 │ └── api │ ├── user.js # 用户模块 │ ├── login.js # 登录、权限 │ └── common.js # 分页、字典、公共接口 ├── .env.development # 开发环境变量 ├── .env.production # 生产环境变量 ├── vite.config.js # vite代理+构建配置 └── main.js # 入口文件 ``` ### .env.development ```bash # 开发环境 VITE_API_BASE_URL=/api # true=使用mock false=走后端代理 VITE_USE_MOCK=true ``` ### .env.production ```bash # 生产环境 VITE_API_BASE_URL=https://api.xxx.com VITE_USE_MOCK=false ``` > **Tips:** + 本地开发、后端未完成:VITE_USE_MOCK=true 自动拦截接口,使用假数据 + 前后端联调:VITE_USE_MOCK=false 关闭 mock,走 vite 代理请求后端 + 打包上线:自动读取生产环境变量,彻底禁用 mock,无冗余代码 ### polyfill.js ```js /** * 前端全局垫片 Polyfill * 用途:兼容低版本浏览器、旧安卓、老旧Safari、IE * 现代项目不需要可注释减少打包体积 */ // 核心ES6+、数组、对象、正则等补齐 import "core-js/stable"; // 兼容 async/await、Generator import "regenerator-runtime/runtime"; // 补齐 fetch、Request、Response import "whatwg-fetch"; // ========== 手动极简兜底兼容 ========== // 兼容 Object.assign if (!Object.assign) { Object.assign = function (target, ...args) { if (target == null) throw new TypeError("Cannot convert undefined or null to object"); const to = Object(target); args.forEach(source => { if (source && typeof source === "object") { for (const key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { to[key] = source[key]; } } } }); return to; }; } // 兼容 Array.includes if (!Array.prototype.includes) { Array.prototype.includes = function (val) { return this.indexOf(val) !== -1; }; } // 兼容 String.includes if (!String.prototype.includes) { String.prototype.includes = function (search) { return this.indexOf(search) !== -1; }; } export default true; ``` > 安装依赖 ```bash # 生产依赖 npm i core-js regenerator-runtime whatwg-fetch axios -S ``` ### request.js ```js import axios from "axios"; const service = axios.create({ baseURL: import.meta.env.VITE_API_BASE_URL, timeout: 15000, headers: { "Content-Type": "application/json" } }); // 请求拦截 service.interceptors.request.use( (config) => { // 统一注入token // config.headers.token = localStorage.getItem("token") || ""; return config; }, (err) => Promise.reject(err) ); // 响应拦截 service.interceptors.response.use( (res) => res.data, (err) => { console.error("请求异常:", err.message); return Promise.reject(err); } ); export default service; ``` ### mock/index.js ```js import Mock from "mockjs"; // 批量引入所有mock模块 import "./api/user"; import "./api/login"; import "./api/common"; // 全局模拟延迟 Mock.setup({ timeout: "200-600" }); // 环境变量开关 const useMock = import.meta.env.VITE_USE_MOCK === "true"; export function setupMock() { if (useMock) { Mock.start(); console.log("%c✅ Mock模式已开启", "color:green"); } else { Mock.stop(); console.log("%c🔗 关闭Mock,使用后端真实接口", "color:#409eff"); } } ``` > 安装依赖 ```bash # 开发依赖 npm i mockjs -D ``` ### mock/api/login.js ```js import Mock from "mockjs"; /** * 登录接口 * POST /api/login */ Mock.mock("/api/login", "post", (req) => { const body = JSON.parse(req.body); // 简单校验 if (!body.username || !body.password) { return { code: 400, msg: "账号密码不能为空", data: null }; } return { code: 200, msg: "登录成功", data: { token: Mock.Random.string(32), userId: Mock.Random.id(), username: body.username, role: "admin" } }; }); /** * 模拟 500 服务异常 */ Mock.mock("/api/error/server", "get", () => { return { code: 500, msg: "服务器内部错误", data: null }; }); ``` ### mock/api/user.js ```js import Mock from "mockjs"; /** * 用户分页列表 GET * /api/user/page */ Mock.mock("/api/user/page", "get", (req) => { // 解析url参数 const params = new URLSearchParams(req.url.split("?")[1]); const page = Number(params.get("page")) || 1; const pageSize = Number(params.get("pageSize")) || 10; return Mock.mock({ code: 200, msg: "查询成功", data: { total: 56, page, pageSize, "list|10": [ { "id|+1": 1001, name: "@cname", phone: /1[3-9]\d{9}/, email: "@email", address: "@county(true)", createTime: "@datetime", "status|1": [0, 1] // 0禁用 1正常 } ] } }); }); /** * 新增用户 POST */ Mock.mock("/api/user/add", "post", () => { return { code: 200, msg: "新增成功", data: null }; }); /** * 删除用户 DELETE */ Mock.mock(/\/api\/user\/delete\/\d+/, "delete", () => { return { code: 200, msg: "删除成功", data: null }; }); ``` ### mock/api/common.js ```js import Mock from "mockjs"; // 部门下拉 Mock.mock("/api/dict/dept", "get", () => { return { code: 200, data: [ { label: "研发部", value: 1 }, { label: "产品部", value: 2 }, { label: "运营部", value: 3 }, { label: "人事部", value: 4 } ] }; }); // 模拟无权限 403 Mock.mock("/api/forbidden", "get", () => { return { code: 403, msg: "暂无访问权限", data: null }; }); ``` ### vite.config.js ```js import { defineConfig } from "vite"; import vue from "@vitejs/plugin-vue"; export default defineConfig({ plugins: [vue()], resolve: { alias: { "@": "/src" } }, // 浏览器兼容 build: { target: "es2015", polyfillModulePreload: true }, // 开发跨域代理 server: { proxy: { "/api": { target: "http://localhost:8080", changeOrigin: true, rewrite: true } } } }); ``` ### main.js ```js // 1. 优先加载兼容垫片 import "@/utils/polyfill"; // 2. 初始化Mock import { setupMock } from "@/mock/index"; setupMock(); // 3. 全局挂载请求 import request from "@/utils/request"; import { createApp } from "vue"; import App from "@/App.vue"; const app = createApp(App); app.globalProperties.$http = request; app.mount("#app"); ``` ### 业务页面调用示例 ```js import request from "@/utils/request"; // 分页用户列表 async function getUserPage() { const res = await request.get("/api/user/page", { params: { page: 1, pageSize: 10 } }); console.log("用户列表:", res.data); } // 登录 async function login() { const res = await request.post("/api/login", { username: "admin", password: "123456" }); console.log("登录结果:", res); } getUserPage(); ``` ## 一个基于 Vue 3 的典型工程项目目录结构 ```bash my-vue-project/ ├── public/ # 静态资源(不经过构建处理) │ ├── favicon.ico │ └── index.html │ ├── src/ # 源代码主目录 │ ├── api/ # 存放所有与后端交互的 JS 文件 │ │ ├── user.js # 用户相关接口(登录、获取信息等) │ │ └── product.js # 商品相关接口 │ │ │ ├── assets/ # 需要经过构建工具处理的资源 │ │ ├── images/ # 图片资源 │ │ ├── fonts/ # 字体文件 │ │ └── styles/ # 全局样式文件(CSS/SCSS/Less) │ │ ├── reset.css # 重置样式 │ │ ├── variables.css # CSS 变量或主题变量 │ │ └── global.css # 全局公共样式 │ │ │ ├── components/ # 可复用的 Vue 组件(.vue 文件) │ │ ├── common/ # 非常通用的组件(如 Button、Modal) │ │ │ ├── AppButton.vue │ │ │ └── AppModal.vue │ │ └── layout/ # 布局相关组件 │ │ ├── AppHeader.vue │ │ └── AppFooter.vue │ │ │ ├── composables/ # (可选)组合式函数(.js 或 .ts) │ │ └── useCounter.js │ │ │ ├── layouts/ # 页面布局骨架(.vue 文件) │ │ ├── DefaultLayout.vue │ │ └── AuthLayout.vue │ │ │ ├── router/ # 路由配置(JS) │ │ └── index.js │ │ │ ├── store/ # 状态管理(Pinia / Vuex,JS 文件) │ │ ├── modules/ │ │ │ ├── user.js │ │ │ └── cart.js │ │ └── index.js │ │ │ ├── utils/ # 工具函数(纯 JS) │ │ ├── request.js # axios 封装 │ │ ├── format.js # 日期、金额格式化 │ │ └── validate.js # 表单校验 │ │ │ ├── views/ # 页面级 Vue 组件(路由对应的页面) │ │ ├── HomeView.vue │ │ ├── AboutView.vue │ │ └── user/ │ │ ├── LoginView.vue │ │ └── ProfileView.vue │ │ │ ├── App.vue # 根组件 │ └── main.js # 应用入口(JS) │ ├── .gitignore ├── index.html # (Vite 模式)入口 HTML ├── package.json ├── vite.config.js # 或 vue.config.js └── README.md ``` ### 文件放置规则说明 |文件类型|主要存放位置|说明| |--|--|--| |.vue|components/、views/、layouts/|组件按粒度分级:复用小组件放 components,路由页面放 views,布局骨架放 layouts| |.js|api/、router/、store/、utils/、composables/、main.js|按功能模块划分:接口、路由、状态、工具函数、入口脚本| |.css|assets/styles/|全局样式放在 assets/styles,组件内的样式写在 .vue 文件中的 `<style>` 块里(作用域可通过 scoped 控制)| > **补充建议** + 组件内样式:推荐使用 `<style scoped>` 写在对应的 .vue 文件里,避免全局污染。 + 全局 CSS 引入:在 main.js 中通过 import './assets/styles/global.css' 导入。 + 预处理器:如需使用 SCSS/Less,可在 assets/styles/ 下新建 global.scss,并在 main.js 中引入。 + 命名规范:组件文件使用 PascalCase(如 UserProfile.vue),工具类 JS 文件使用 camelCase(如 formatDate.js)
扫一扫手机看
点击排行
windows 文件资源管理器使用
Layui 弹窗open使用说明
SQL Server 中字符串函数使用
C# 使用QQ邮箱代理做邮件接收功能
SQL Server关于apply的两种形式cross apply 和 outer apply
ASP.NET MVC 模型的自定义验证
nvm安装及常用命令
SQL Server 中数据类型转换
SQL Server 中WITH AS短语的使用
IE浏览器下AJAX缓存问题导致数据不更新的解决办法
订阅号