Vue3+Vite 本地数据模拟 JSON 读取和Mock 方案完整讲解总结
若依原版使用
vite‑plugin‑mock+ mockjs,但是该插件停止维护、Vite 版本升级容易报错。我们抛弃插件,采用两套无插件方案,分别应对不同业务场景,兼容静态 JSON 文件模拟和 JS 内存 Mock,api 层、页面代码完全统一,后期无缝切换真实后端接口。
一、两种数据来源说明
1. public 目录下 JSON 文件(静态文件模拟)
- 文件放在
public/,Vite 不会编译,打包后直接复制到 dist 目录。 - 获取方式:网络请求 fetch /axios get 请求 ,不能
import导入。 - 特点:
✅ 打包上线后,可以直接修改服务器上 json 文件,刷新页面立即生效,不需要重新打包项目
❌ 只能 GET 请求,无法接收 post 参数,不能写业务逻辑,没有分页、校验能力
适合:字典、省市、固定配置等只读静态数据
2. src 内部 JSON 文件(import 导入)
文件放在src/assets/xxx.json
import dict from '@/assets/dict.json'
✅ 直接导入,简单方便
❌ json 会被编译打进 js,线上修改 json 必须重新打包部署
适合写死的常量,不适合做 mock 接口模拟
3. JS 内存 Mock(request 拦截模拟接口,重点)
把模拟数据写在.js文件,在 axios 封装的 request 函数内部拦截 url,直接返回模拟数据,不走网络请求。
✅ 支持 GET/POST/PUT/DELETE,分页、参数校验、模拟新增删除逻辑,可以写 JS 代码
✅ 零第三方 mock 插件,无版本坑,只在开发环境执行,生产环境完全移除 mock 逻辑
❌ 数据存浏览器内存,刷新页面数据重置;打包后 mock 代码不会参与线上运行
适合:登录、用户 CRUD、分页列表、表单提交等绝大部分后台业务
二、项目目录(模仿若依结构)
├── public
│ └── mock-json # public静态json mock,打包后可修改
│ ├── dict.json
│ └── area.json
├── src
│ ├── api #接口层,和若依结构一致
│ │ ├── user.js
│ │ └── dict.js
│ ├── mockData #JS内存mock,开发环境模拟接口逻辑
│ │ ├── user.js
│ │ └── login.js
│ ├── utils
│ │ └── request.js #axios封装,两套mock在这里统一处理
│ ├── views #页面组件,业务层完全感知不到底层mock类型
│ ├── .env.development #开发环境变量
│ └── .env.production #生产环境变量
public/mock‑json/dict.json 示例
{
"code": 200,
"msg": "查询成功",
"data": [
{"dictValue":"1","dictLabel":"启用"},
{"dictValue":"0","dictLabel":"禁用"}
]
}
src/mockData/user.js(JS 内存 mock)
//模拟数据库,内存存储,刷新重置
let userDB = [
{id:1, username:"admin", nickName:"管理员", status:1},
{id:2, username:"test", nickName:"测试用户", status:0}
]
//用户分页列表
export function getUserListMock(params){
const {pageNum=1, pageSize=10} = params
const start = (pageNum-1)*pageSize
return {
code:200,
msg:"查询成功",
data:{
total: userDB.length,
records: userDB.slice(start, start+pageSize)
}
}
}
//新增用户
export function addUserMock(form){
const newId = Math.max(...userDB.map(i=>i.id)) + 1
userDB.push({id:newId, ...form})
return {code:200, msg:"新增成功"}
}
//登录校验
export function loginMock(body){
if(body.username === 'admin' && body.password === '123456'){
return {code:200, data:{token:"mock‑token‑001"}}
}
return {code:500, msg:"账号密码错误"}
}
src/utils/request.js【核心】两套 mock 共存
import axios from 'axios'
import { getUserListMock, addUserMock, loginMock } from '@/mockData/user'
const service = axios.create({
baseURL: import.meta.env.VITE_API_BASE_URL,
timeout:8000
})
//统一请求封装,在这里做mock拦截
const request = async (config) =>{
const {url, method, params, data} = config
//只开发环境启用mock
if(import.meta.env.DEV){
//模拟网络延迟
await new Promise(resolve=>setTimeout(resolve,250))
// ========== JS内存Mock:登录、用户CRUD ==========
if(url === '/system/login' && method.toUpperCase() === 'POST'){
return loginMock(data)
}
if(url === '/system/user/list' && method.toUpperCase() === 'GET'){
return getUserListMock(params)
}
if(url === '/system/user/add' && method.toUpperCase() === 'POST'){
return addUserMock(data)
}
// ========== public静态JSON Mock:字典只读数据 ==========
if(url === '/system/dict/list'){
const res = await fetch(import.meta.env.BASE_URL + 'mock‑json/dict.json')
return await res.json()
}
}
//mock未命中,走真实axios请求后端
const res = await service(config)
return res.data
}
export default request
api 层(和若依写法完全一致,上层业务无感知)
src/api/user.js 使用 JS 内存 mock
import request from '@/utils/request'
export function login(data){
return request({url:'/system/login',method:'post',data})
}
export function getUserList(params){
return request({url:'/system/user/list',method:'get',params})
}
export function addUser(data){
return request({url:'/system/user/add',method:'post',data})
}
src/api/dict.js 使用 public json mock
import request from '@/utils/request'
export function getDictList(){
return request({url:'/system/dict/list',method:'get'})
}
vue 页面调用,两种 mock 调用方式完全一样
<script setup>
import {getUserList} from '@/api/user'
import {getDictList} from '@/api/dict'
async function load(){
//JS内存mock,用户分页
const userRes = await getUserList({pageNum:1,pageSize:10})
//public json mock,字典
const dictRes = await getDictList()
console.log(userRes, dictRes)
}
load()
</script>
三、环境变量配置
.env.development
VITE_API_BASE_URL=/api
.env.production
VITE_API_BASE_URL=/api
生产环境
import.meta.env.DEV为 false,所有 mock 代码全部不会执行,直接请求后端接口。
四、方案选型对照表(重点总结)
表格
| 方案 | 实现方式 | 支持请求 | 优势 | 劣势 | 适用场景 |
|---|---|---|---|---|---|
| JS 内存 Mock | request 拦截,src/mockData js 文件 | GET/POST/PUT/DELETE,支持分页、参数校验 | 零插件,可写业务逻辑,接口格式和后端对齐 | 数据内存存储,刷新重置,线上失效 | 登录、新增、编辑、删除、分页列表,后台 CRUD 业务 |
| public JSON Mock | public 下放 json 文件,fetch/axios get | 仅 GET 只读 | 打包后可直接修改 json 文件,无需重新构建 | 不能处理 post,无法写逻辑 | 字典、省市、固定配置等静态只读数据 |
| src/assets import json | 直接 import json | 无网络请求 | 简单直接 | 修改必须重新打包 | 项目固定常量,不做接口模拟 |
| vite‑plugin‑mock | 第三方插件 | 全部 http 方法 | 配置齐全 | 停止维护、版本坑多,升级 Vite 容易报错 | 不推荐新项目使用 |
五、重要踩坑总结
- public 文件夹下 json 不能 import 导入,必须通过网络请求获取;src 下面 json 可以 import。
- public json 只能 GET,不要用来模拟登录、新增等 POST 接口。
- public 路径必须以
/开头,部署二级目录使用import.meta.env.BASE_URL拼接路径。 - json 文件不能写注释,否则读取直接报错。
- JS 内存 mock 数据保存在浏览器内存,刷新页面恢复初始模拟数据。
- 对接真实后端:只需要注释掉 request.js 里面全部 mock 匹配代码,api、页面代码一行不用修改。
- 生产环境两套 mock 都不会运行,不会污染线上代码。
六、和原版若依 mock 对比
- 原版若依:依赖
vite‑plugin‑mock插件,基于 mockjs,插件不再维护,Vite 新版本兼容差。 - 当前方案:去除第三方 mock 插件,保留若依的 api 分层思想,两套 mock 按需选用,业务代码完全和若依保持一致,后期对接后端无缝切换。
开发小技巧:需要关闭 mock,直接注释 request.js 中
if(import.meta.env.DEV)内部 mock 代码块即可。