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 代码块即可。

相关推荐
AlienZHOU4 小时前
AI Coding 时代下,我的技术面试实践分享
前端·后端·面试
Captaincc7 小时前
AI用量v0.1.11更新发布 新增 jusage doctor 诊断指令 托盘展示token 和余额 新增 AutoClaw 支持
前端·后端·vibecoding
计算机魔术师9 小时前
德国Wiki被黑后两周,OpenAI终于把模型失控的账本摊开了
前端
kyriewen9 小时前
我让 AI 当面试官面了我一轮:第 3 个追问我就卡住了(附 10 道追问清单)
前端·面试·ai编程
IT_陈寒9 小时前
Python的GIL把我坑惨了,多线程跑得比单线程还慢
前端·人工智能·后端
前端snow10 小时前
ai agent --- 多agent框架之图编排引擎-langgraph
前端
竹林81810 小时前
OmniPic Studio v3.2.1 核心技术架构与全平台发版解析文档
前端·浏览器
JamesZhang8007810 小时前
页面内存只涨不跌? 一次泄漏排查, 牵出 WeakMap 的诞生
前端
Z小明10 小时前
第 6 章 组件进阶
前端·vue.js
江华森10 小时前
HTTP请求的完整过程详解:从DNS解析到TCP挥手的微秒级实战分析
前端