> 技术文档 > 【前后端】node mock.js+json-server_node.js写一个获取json数据的接口

【前后端】node mock.js+json-server_node.js写一个获取json数据的接口


JSON-Server

一个在前端本地运行,可以存储json数据的server。前端开发可以模拟服务端接口数据,在本地搭建一个JSON服务,自己产生测试数据。

  1. 使用npm全局安装json-server :npm install -g json-server
  2. 可以通过查看版本号,来测试是否安装成功:json-server -v
  3. 创建json数据——db.json
    在任意一个文件夹下(此处假设创建一个server文件夹),进入到该文件夹里面,执行代码 json-server --watch db.json
  4. 此时文件夹下多出一个db.json文件
  5. 启动json-server --watch db.json,访问 http://localhost:3000/
  6. 分别点击/posts /comments /profile /db链接,我们可以看到访问不同URL返回不同的json数据。其中 /db返回的是整个json文件的数据。
  • 修改端口号
    默认3000 --port 3004或者在db.json同级文件夹新建一个package.json,在script配置添加运行命令:
{ \"scripts\": { \"mock\": \"json-server db.json --port 3004\" }}//运行时, 直接在当前文件夹下执行 npm run mock
  • 操作数据 | 增删改查
    json-server 支持 restful 风格的api,可以通过不同的请求方式,对数据进行增删改查等不同的操作。
    先修改db.json文件:
{ \"users\": [ { \"id\": 1, \"name\": \"liaoyi\", \"phone\": \"13246566776\", \"age\": 22, \"classId\": \"1002\" }, { \"name\": \"林更新\", \"age\": \"44\", \"id\": 4, \"classId\": \"1003\" }, { \"name\": \"李响\", \"phone\": \"18779756778\", \"age\": \"26\", \"id\": 5, \"classId\": \"1003\" }, { \"name\": \"陈温柔\", \"phone\": \"18779756000\", \"age\": \"22\", \"id\": 6, \"sex\": \"0\", \"classId\": \"1004\" }, { \"name\": \"夏琪\", \"phone\": \"13246579999\", \"age\": \"22\", \"id\": 7, \"classId\": \"1004\" } ], \"class\": [ { \"id\": \"1\", \"title\": \"前端\", \"staff\": [ \"1002\", \"1004\" ] }, { \"id\": \"2\", \"title\": \"后端\", \"staff\": [ \"1003\" ] } ], \"fruits\": [ { \"id\": 1, \"name\": \"苹果\", \"price\": 1.28 }, { \"id\": 2, \"name\": \"橘子\", \"price\": 3.88 }, { \"id\": 3, \"name\": \"宁夏西瓜\", \"price\": 1.98 }, { \"id\": 4, \"name\": \"麒麟西瓜\", \"price\": 3.98 }, { \"id\": 5, \"name\": \"红蛇果\", \"price\": 2.5 }, { \"id\": 6, \"name\": \"黑皮西瓜\", \"price\": 0.98 }, { \"id\": 7, \"name\": \"红心火龙果\", \"price\": 2.69 }, { \"id\": 8, \"name\": \"国产火龙果\", \"price\": 1.69 }, { \"id\": 9, \"name\": \"海南荔枝\", \"price\": 9.9 }, { \"id\": 10, \"name\": \"陕西冬枣\", \"price\": 5.39 }, { \"id\": 11, \"name\": \"软籽石榴\", \"price\": 2.39 }, { \"id\": 12, \"name\": \"蜜橘\", \"price\": 1.99 }, { \"id\": 13, \"name\": \"海南香蕉\", \"price\": 1.45 } ], \"person\": [ { \"name\": { \"firstname\": \"liao\", \"lastname\": \"yi\" }, \"pwd\": \"qwerst54\" }, { \"name\": { \"firstname\": \"wang\", \"lastname\": \"wu\" }, \"pwd\": \"adasff11\" } ]}
  • get 获取数据
    浏览器可以直接访问GET请求,可以直接在浏览器访问就能看到返回的json数据。
    获取所有用户数据(对象数组): http://localhost:3004/users
    获取所有水果数据:http://localhost:3004/fruits
    获取数据
    根据 id 获取 users 数据:http://localhost:3004/users/1
//get请求的query参数http://localhost:3004/users?id=1//传入不同的条件// 查找名字为 \'liaoyi\' 的用户http://localhost:3004/users?name=liaoyi//多个条件 用&符号连接:http://localhost:3004/fruits?name=橘子&price=3.88//甚至还可以使用对象取属性值 obj.key 的方式 http://localhost:3004/person?name.firstname=liao//分页采用 _page 来设置页码,// _limit 来控制每页显示条数。//如果没有指定 _limit ,默认每页显示10条。http://localhost:3004/fruits?_page=1&_limit=5http://localhost:3004/fruits?_page=1&_limit=10http://localhost:3004/fruits?_page=2&_limit=5//排序采用 _sort 来指定要排序的字段// _order 来指定排序是正排序还是逆排序(asc | desc ,默认是asc)。http://localhost:3004/fruits?_sort=pricehttp://localhost:3004/fruits?_sort=price&_order=desc//获取局部数据//_start 来指定开始位置, _end 来指定结束位置、//或者_limit指定从开始位置起往后取几个数据。类似Array.slice() 方法# 使用 _endhttp://localhost:3004/fruits?_start=2&_end=4# 使用 _limithttp://localhost:3004/fruits?_start=2&_limit=4//获取符合某个范围的数据1. 使用 _gte 和 _lte 来设置一个取值范围 :2. 使用 _ne 来获取不包含某个值的数据3. 采用 _like 来设置匹配某个字符串(或正则表达式)http://localhost:3004/fruits?id_gte=4&id_lte=6http://localhost:3004/fruits?id_ne=1&id_ne=10http://localhost:3004/fruits?name_like=//搜索功能 采用 q 来设置搜索内容:http://localhost:3004/fruits?q=
  • 除get请求外,其他请求方式需要我们通过 api 调试工具或者代码的方式来使用。如apifox
<template> <el-button @click=\"add\"> 发送请求 </el-button></template><script setup> import axios from \'axios\' const url = \'http://localhost:3004/users\' const add = async () => { const data = { name: \'林更新\', phone: \'18779756000\', age: \'22\' } const { data: res } = await axios({ method: \'post\', url, data }) console.log(\'res\', res) }</script><template> <el-button @click=\"deleteUser\"> 删除用户 </el-button></template><script setup>import axios from \'axios\'const userId = 3const url = `http://localhost:3004/users/${userId}`const deleteUser = async () => { const res = await axios({ method: \'delete\', url }) console.log(\'res\', res)}</script>

PUT方法会更新整个资源对象,前端没有给出的字段,会自动清空。但是使用put修改后会有一个问题,只会保留提交的字段,没有提交的字段在json中将会被删除
patch 修改数据 :只修改请求的字段,没有请求的字段将会被保留。

<template> <el-button @click=\"reviseUser\"> put 修改用户 </el-button></template><script setup>import axios from \'axios\'const userId = 4const url = `http://localhost:3004/users/${userId}`const reviseUser = async () => { const data = { \"name\": \"林更新\", \"age\": \"44\" } const res = await axios({ method: \'put\', url, data }) console.log(\'res\', res)}</script><template> <el-button @click=\"reviseUser\"> patch修改用户 </el-button></template><script setup>import axios from \'axios\'const userId = 8const url = `http://localhost:3004/users/${userId}`const reviseUser = async () => { const data = { name: \"陈温柔\", age: \"22\", sex: \"0\"} const res = await axios({ method: \'patch\', url, data }) console.log(\'res\', res)}</script>
  • 多表查询 | 关联检索
  1. 向上关联
    通过 _expand 方式检索关联父级数据,多对一关系,所以条件是单数。
    这里的 _expand=class 匹配即和 users 对象中的 classId做关联,但是已经存在classId字段则写出 class, 比如检索的是 repaId 写成 repa
  2. 通过 _embed 方式检索关联子级数据
    注意: 这里_embed 需要和子表名 (要关联的子集属性名) 匹配。一对多关系,所以匹配条件是负数。
//向上关联父级数据//class 是一个别名http://localhost:3004/users?_expand=class//res:[ { \"id\": 1, \"name\": \"liaoyi\", \"phone\": \"13246566776\", \"age\": 22, \"classId\": \"1\", \"class\": { \"id\": \"1\", \"title\": \"前端\", \"staff\": [ \"7\", \"6\", \"1\" ] } }, { \"name\": \"林更新\", \"age\": \"44\", \"id\": 4, \"classId\": \"2\", \"class\": { \"id\": \"2\", \"title\": \"后端\", \"staff\": [ \"4\", \"5\" ] } }, { \"name\": \"李响\", \"phone\": \"18779756778\", \"age\": \"26\", \"id\": 5, \"classId\": \"2\", \"class\": { \"id\": \"2\", \"title\": \"后端\", \"staff\": [ \"4\", \"5\" ] } }, { \"name\": \"陈温柔\", \"phone\": \"18779756000\", \"age\": \"22\", \"id\": 6, \"sex\": \"0\", \"classId\": \"1\", \"class\": { \"id\": \"1\", \"title\": \"前端\", \"staff\": [ \"7\", \"6\", \"1\" ] } }, { \"name\": \"夏琪\", \"phone\": \"13246579999\", \"age\": \"22\", \"id\": 7, \"classId\": \"1\", \"class\": { \"id\": \"1\", \"title\": \"前端\", \"staff\": [ \"7\", \"6\", \"1\" ] } }]//向下关联子级数据http://localhost:3004/classes?_embed=users//res:[ { \"id\": \"1\", \"title\": \"前端\", \"staffIds\": [ \"1001\", \"1004\", \"1005\" ], \"users\": [ { \"id\": \"1001\", \"name\": \"liaoyi\", \"phone\": \"13246566776\", \"age\": 22, \"classId\": \"1\" }, { \"name\": \"陈温柔\", \"phone\": \"18779756000\", \"age\": \"22\", \"id\": \"1004\", \"sex\": \"0\", \"classId\": \"1\" }, { \"name\": \"夏琪\", \"phone\": \"13246579999\", \"age\": \"22\", \"id\": \"1005\", \"classId\": \"1\" } ] }, { \"id\": \"2\", \"title\": \"后端\", \"staffIds\": [ \"1002\", \"1003\" ], \"users\": [ { \"name\": \"林更新\", \"age\": \"44\", \"id\": \"1002\", \"classId\": \"2\" }, { \"name\": \"李响\", \"phone\": \"18779756778\", \"age\": \"26\", \"id\": \"1003\", \"classId\": \"2\" } ] }]
  • 静态部署
    新增配置文件 config.json 并写入
{ \"port\": \"3000\", // 设置端口号 \"watch\": true, // 是否开启监听 \"static\": \"./public/\", // 静态资源目录 \"read-only\": false, // 是否只读 \"no-cors\": true, // 是否支持跨域 \"no-gzip\": false // 是否开启压缩}//启动命令json-server --watch data.json config.json//或者放入package.json+npm run mock{ \"scripts\": { \"mock\": \"json-server --watch data.json config.json\" }}

mock.js

  • Mock.js + json-server 模拟数据
  1. 创建一个文件夹名为 mock_json
  2. 进入文件夹后初始化package.json 文件
  3. 下载依赖
mkdir mock_jsoncd mock_jsonnpm init npm install json-server mockjs
  1. 添加启动脚本
{ \"name\": \"mock_json\", \"scripts\": { \"dev\": \"json-server --watch db.js --port 3000\" }, \"dependencies\": { \"json-server\": \"^0.17.4\", \"mockjs\": \"^1.1.0\" }}
  1. 新建 db.js 文件
const Mock = require(\'mockjs\')const data = Mock.mock({ \'users|10-20\': [{ \'id|+1\': \'1\', \'name\': \'@name\', \'sex|1\': [\'男\', \'女\'], \'age|18-60\': 1, \'address\': \'@county(true)\', \'phone\': /^1[34578]\\d{9}$/, \'email\': \'@email\', \'birthday\': \'@date\', \'avatar\': \'@image(200x200, #50B347, #FFF, #78C3FC)\', \'desc\': \'@cparagraph(1, 3)\' }], \'products|122000\': [{ \'id|+1\': 1, \'name\': \'@word(3,5)\', \'price\': \'@integer(100,999)\', \'quantity\': \'@integer(1,50)\', \'brief\': \'@cparagraph(1, 3)\' }],})// 想要用 json-server 识别mockjs的模拟数据内容,需要使用 module.exports 进行模块的对外暴露,并且暴露的类型必须是函数module.exports = () => data/* 上面👆 products 有十二万数据,不能直接打开浏览器访问http://localhost:3000/products,浏览器会奔溃的 需要使用查询参分页查询 如: http://localhost:3000/products?_page=1&_limit=10 */
  1. 启动项目
npm run dev

注意⚠️:

  1. 想要用 json-server 识别mockjs的模拟数据内容,需要使用 module.exports 进行模块的对外暴露,并且暴露的类型必须是函数。
  2. 上面 products 我们模拟了十二万条数据,启动时会有点慢,并且不能直接使用浏览器访问http://localhost:3000/products,浏览器会奔溃的。需要使用查询参分页查询, 如:http://localhost:3000/products?_page=1&_limit=10