Vue3+Vite 本地数据模拟 JSON 读取和Mock 方案完整讲解总结

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 容易报错 不推荐新项目使用

五、重要踩坑总结

  1. public 文件夹下 json 不能 import 导入,必须通过网络请求获取;src 下面 json 可以 import。
  2. public json 只能 GET,不要用来模拟登录、新增等 POST 接口
  3. public 路径必须以/开头,部署二级目录使用import.meta.env.BASE_URL拼接路径。
  4. json 文件不能写注释,否则读取直接报错。
  5. JS 内存 mock 数据保存在浏览器内存,刷新页面恢复初始模拟数据。
  6. 对接真实后端:只需要注释掉 request.js 里面全部 mock 匹配代码,api、页面代码一行不用修改
  7. 生产环境两套 mock 都不会运行,不会污染线上代码。

六、和原版若依 mock 对比

  • 原版若依:依赖vite‑plugin‑mock插件,基于 mockjs,插件不再维护,Vite 新版本兼容差。
  • 当前方案:去除第三方 mock 插件,保留若依的 api 分层思想,两套 mock 按需选用,业务代码完全和若依保持一致,后期对接后端无缝切换。

开发小技巧:需要关闭 mock,直接注释 request.js 中if(import.meta.env.DEV)内部 mock 代码块即可。

相关推荐
jjw_zyfx25 分钟前
vue3 vite 前端录制浏览器界面视频并保存下载
前端·音视频
南雨北斗30 分钟前
vue3项目表单验证 input 添加高亮样式
前端
:-)43 分钟前
idea中的vue文件没有高亮显示
前端·javascript·vue.js·ecmascript·intellij-idea
IPdodo_1 小时前
2026年AI 数据采集代理 IP 选型:成功率、并发、轮换与成本评估
前端·网络·人工智能·chrome·python·http·网络调试
计算机魔术师1 小时前
AI问诊5秒出结果,医生反而更忙了
前端
郭邯1 小时前
从需求到上线:我用 AI 辅助开发了一个在线倒计时器
前端
Damai1 小时前
Next.js 切换动态路由后,为什么页面还保留着上一个分类的数据?
前端·react.js
程序员鱼皮1 小时前
爆火的《牛来》模型正式发布!DeepSeek 的排名又下降了。。
前端·后端·ai编程
MocMoc1 小时前
从零落地全栈 Monorepo:Turbo + npm workspaces 实战(附一个记账小应用)
前端