内容简介:新建db.json用于测试
#Linxu/Mac os sudo npm install json-server -g #window npm install json-server -g 复制代码
新建db.json用于测试 json-server db.json -p 3003
,-p 指定端口号为3003
{ "news":[ { "id": 1, "title": "曹县宣布昨日晚间登日成功", "date": "2016-08-12", "likes": 55, "views": 100086 }, { "id": 2, "title": "长江流域首次发现海豚", "date": "2016-08-12", "likes": 505, "views": 9800 } ], "comments":[ { "id": 1, "news_id": 1, "data": [ { "id": 1, "content": "支持党中央决定" }, { "id": 2, "content": "抄写党章势在必行!" } ] } ] } 复制代码
出现错误:
/usr/bin/env: node: No such file or directory
解决
ln -s /usr/bin/nodejs /usr/bin/node 复制代码
json-server requires at least version 6 of Node, please upgrade
解决
sudo npm cache clean -f sudo npm install -g n sudo n stable 复制代码
快速启动脚本
db.json 目录下新建 package.json
, 运行 npm run mock
{ "scripts": { "mock": "json-server db.json --port 3003" } } 复制代码
简单的数据操作
- json-server和postman 简单教程 postman是模拟请求的开发神器
-
POST, PUT, PATCH or DELETE 这些操作会自动的保存在db.json文件里,请求必须是Json格式,包含头文件
Content-Type: application/json
否则返回的虽然是200 OK,但是不会修改数据
GET
http://localhost:3003/db ==> db.json
http://localhost:3003/news ==> news节点
POST
Postman向 http://localhost:3003/news
传参数
"id": 3, "title": "我是新加入的新闻", "date": "2016-08-12", "likes": 0, "views": 0 复制代码
json-server 后台反应
POST /news?id=3&title=%E6%88%91%E6%98%AF%E6%96%B0%E5%8A%A0%E5%85%A5%E7%9A%84%E6%96%B0%E9%97%BB&date=2016-08-12&likes=0&views=0 201 2.622 ms - 13 复制代码
使用url encode 解码点击UrlDecode解码
POST /news?id=3&title=我是新加入的新闻&date=2016-08-12&likes=0&views=0 201 2.622 ms - 13 复制代码
PUT
json-server 后台打印
PUT /news?title=我是新加入的新闻&date=2016-08-12&likes=55&views=100086 404 2.430 ms - 2 复制代码
模拟动态数据
简单的返回数组
/mock/db.js
module.exports = function() { var data = { users: [] } // Create 1000 users for (var i = 0; i < 1000; i++) { data.users.push({ id: i, name: 'user' + i }) } return data } 复制代码
运行
json-server db.js -p 3003 复制代码
访问
http://localhost:3003/users 复制代码
返回
[ { "id": 0, "name": "user0" }, { "id": 1, "name": "user1" } ...... ] 复制代码
拒绝僵硬的数据,引入mockjs
安装mockjs 在 /mock
目录下安装
npm install mockjs --save 复制代码
示例:返回100条新闻数据
// # /mock/db.js let Mock = require('mockjs'); let Random = Mock.Random; module.exports = function() { var data = { news: [] }; var images = [1,2,3].map(x=>Random.image('200x100', Random.color(), Random.word(2,6))); for (var i = 0; i < 100; i++) { var content = Random.cparagraph(0,10); data.news.push({ id: i, title: Random.cword(8,20), desc: content.substr(0,40), tag: Random.cword(2,6), views: Random.integer(100,5000), images: images.slice(0,Random.integer(1,3)) }) } return data } 复制代码
运行
json-server db.js -p 3000 复制代码
访问 http://localhost:3000/news
返回
[ { "id": 0, "title": "元小总小把清保住影办历战资和总由", "desc": "共先定制向向圆适者定书她规置斗平相。要广确但教金更前三响角面等以白。眼查何参提适", "tag": "值集空", "views": 3810, "images": [ "http://dummyimage.com/200x100/79f2a5&text=别角置", "http://dummyimage.com/200x100/f28279&text=收面几容受取", "http://dummyimage.com/200x100/7993f2&text=做件" ] }, ...... ] 复制代码
Mock 语法
Mock.mock
repeat 方法(部分)
Mock.mock({ "string|5": "★" => "string": "★★★★★" "string|1-10": "★" => "string": "★★" "number|1-100": 100 => "number": 85 "number|1-100.2": 100 => "number": 25.69 }) 复制代码
Mock.Random
Random.boolean() => true false 各50% Random.integer(60, 100) => 78 Random.float(60, 100) => 89.565475 Random.range(60, 100) => [60,61,62,...,99] Random.date() => "2018-12-28" Random.image('200x100','#396') => "http://dummyimage.com/200x100/396" Random.color() => "#79d8f2" (默认使用hex颜色) Random.county(true) => "浙江省 舟山市 岱山县" 复制代码
- Rnadom.image
Random.image() // => "http://dummyimage.com/125x125" Random.image('200x100') // => "http://dummyimage.com/200x100" Random.image('200x100', '#fb0a2a') // => "http://dummyimage.com/200x100/fb0a2a" Random.image('200x100', '#02adea', 'Hello') // => "http://dummyimage.com/200x100/02adea&text=Hello" Random.image('200x100', '#00405d', '#FFF', 'Mock.js') // => "http://dummyimage.com/200x100/00405d/FFF&text=Mock.js" Random.image('200x100', '#ffcc33', '#FFF', 'png', '!') // => "http://dummyimage.com/200x100/ffcc33/FFF.png&text=!" 复制代码
- Text
paragraph-> centence -> word -> title #中文 Random.cparagraph() Random.cparagraph( len ) Random.cparagraph( min, max ) #随机生成一段中文文本 Random.csentence() Random.csentence( len ) Random.csentence( min, max ) # 随机生成一个汉字 Random.cword() Random.cword( pool ) Random.cword( length ) Random.cword( pool, length ) Random.cword( min, max ) Random.cword( pool, min, max ) 复制代码
进阶
加工数据
Filter
对应的数据九宫格
comments:[ { "id": 1, "news_id": 1, "author":{ "name":"a1", "age":32 }, "data": [ { "id": 1, "content": "支持党中央决定" }, { "id": 2, "content": "抄写党章势在必行!" } ] } ] 复制代码
查询语句:
GET /comments?id=1r&new_id=2 GET /comments?author.name=a1 复制代码
Paginate 分页
GET /posts?_page=7 GET /posts?_page=7&_limit=20 复制代码
- 默认返回 10 items
- 表头会出现 first, prev, next and last 的直接访问地址,x-total-count数据总数信息
access-control-expose-headers →X-Total-Count, Link link →<http://localhost:3000/news?_page=1>; rel="first", <http://localhost:3000/news?_page=2>; rel="next", <http://localhost:3000/news?_page=2>; rel="last" x-total-count →20 复制代码
关系图谱
posts id 和comments id 是关联的
{ "posts": [ { "id": 1, "title": "post的第一个title", "author": "typicode" }, { "id": 2, "title": "post的第二个title", "author": "tangcaiye" } ], "comments": [ { "id": 1, "body": "some comment1111", "postId": 2 }, { "id": 2, "body": "some comment2222", "postId": 1 } ], "profile": { "name": "typicode" } } 复制代码
-
_embed
http://localhost:3000/posts/2?_embed=comments
返回posts/2
下级关联数据comments
{ "id": 2, "title": "post的第二个title", "author": "tangcaiye", "comments": [ { "id": 1, "body": "some comment1111", "postId": 2 } ] } 复制代码
-
_expand
http://localhost:3000/comments/2?_expand=post
返回comments上级关联数据post
{ "id": 2, "body": "some comment2222", "postId": 1, "post": { "id": 1, "title": "post的第一个title", "author": "typicode" } } 复制代码
其他
排序
默认升序
GET /posts?_sort=views&_order=asc GET /posts/1/comments?_sort=votes&_order=asc 复制代码
切片 Slice
包括_star,不包括_end
GET /posts/1/comments?_start=20&_end=30 GET /posts/1/comments?_start=20&_limit=10 复制代码
汇总
# _gte > || _lte < GET /posts?views_gte=10&views_lte=20 # _ne != GET /posts?id_ne=1 # _like 注意title的字段名称 GET /posts?title_like=server # 全局搜索 GET /posts?q=internet # 直接获取数据 GET /db 复制代码
路由设置
注意:没有设置路由(主要是: "host": "0.0.0.0" 属性)之前 json-server --watch db.json
只有本机能访问,也就是局域网外网都不能访问
- 可以用-H 命令指定
json-server --watch db.json -H 0.0.0.0 复制代码
-
host 设置为
127.0.0.1
或者本地局域网IP地址 如192.168.1.168
无效 ,(服务器指定127.0.0.1/ 192.168.1.168是本地调试模式)具体解释网址 大意: 0.0.0.0指的是本机上的所有IPV4地址
IPV4中,0.0.0.0地址被用于表示一个无效的,未知的或者不可用的目标。* 在服务器中,0.0.0.0指的是本机上的所有IPV4地址,如果一个主机有两个IP地址,192.168.1.1 和 10.1.2.1,并且该主机上的一个服务监听的地址是0.0.0.0,那么通过两个ip地址都能够访问该服务。 * 在路由中,0.0.0.0表示的是默认路由,即当路由表中没有找到完全匹配的路由的时候所对应的路由。
设置的两种方法
- 直接命令行指定路由文件
json-server db.js -p 3003 -d 500 -q -r ./routes.json 复制代码
-
json-server.json
文件进行配置后,直接json-server db.json
# /mock/json-server.json { "host": "0.0.0.0", "port": "3003", "watch": false, "delay": 500, "quiet": true, "routes": "./routes.json" } 复制代码
自定义路由,可以指定访问链接返回指定的数据,而且可以动态修改
routes.json
{ "/api/*": "/$1", "/:resource/:id/show": "/:resource/:id", "/posts/:category": "/posts?category=:category", "/articles\\?id=:id": "/posts/:id" } 复制代码
对应的效果
/api/posts # → /posts /api/posts/1 # → /posts/1 /posts/1/show # → /posts/1 /posts/javascript # → /posts?category=javascript /articles?id=1 # → /posts/1 复制代码
"/api/*": "/$1" /:resource /
增加中间件
// hello.js module.exports = (req, res, next) => { res.header('X-Hello', 'World') next() } json-server db.json --middlewares ./hello.js json-server db.json --middlewares ./first.js ./second.js 复制代码
Nodejs Module 不用等后台同事API
为什么学了上面还要学nodejs的案例呢? 因为上面的技能还不能很好的满足开发中REST API的需求
- rount.json 储存在文件中修改比较麻烦
- 只用配置文件,不很好使用Mock的相关功能
- 把配置放在js中相对灵活,能动态的拦截返回和处理相关逻辑
最简单案例
node 安装 json-server模块
$ npm install json-server --save-dev 复制代码
// server.js const jsonServer = require('json-server') const server = jsonServer.create() const router = jsonServer.router('db.json') //默认为当前目录 //const path = require('path') 指定其他目录 //const router = jsonServer.router(path.join(__dirname, 'db.json')) const middlewares = jsonServer.defaults() server.use(middlewares) server.use(router) server.listen(3000, () => { console.log('JSON Server is running') }) // 运行 $ node server.js 复制代码
自定义路由
const jsonServer = require('json-server') const server = jsonServer.create() const router = jsonServer.router('db.json') const middlewares = jsonServer.defaults() // Set default middlewares (logger, static, cors and no-cache) server.use(middlewares) // Add custom routes before JSON Server router server.get('/echo', (req, res) => { res.jsonp(req.query) }) // To handle POST, PUT and PATCH you need to use a body-parser // You can use the one used by JSON Server server.use(jsonServer.bodyParser) server.use((req, res, next) => { if (req.method === 'POST') { req.body.createdAt = Date.now() } // Continue to JSON Server router next() }) // Use default router server.use(router) server.listen(3000, () => { console.log('JSON Server is running') }) 复制代码
对上面的几点进行说明
res.jsonp res ==> respose
res.status(500).jsonp({ error: "error message here" "id": 21, "title": "长江", "date": "2016-09-12", "likes": 509, "views": 9900 }) 复制代码
请求的返回Json格式
{ "error": "error message here" "id": 21, "title": "长江", "date": "2016-09-12", "likes": 509, "views": 9900 } 复制代码
req.body.createdAt = Date.now() 往返回的jons中插入createAt字段,如本应返回
{ "id": 21, "title": "长江", "date": "2016-09-12", "likes": 509, "views": 9900 } 复制代码
加入req.body.createdAt = Date.now()后返回
{ "id": 21, "title": "长江", "date": "2016-09-12", "likes": 509, "views": 9900, "createdAt": 1536476508883, } 复制代码
js 增加router.json 配置
// Add this before server.use(router) server.use(jsonServer.rewriter({ '/api/*': '/$1', '/blog/:resource/:id/show': '/:resource/:id' })) 复制代码
访问控制
const jsonServer = require('json-server') const server = jsonServer.create() const router = jsonServer.router('db.json') const middlewares = jsonServer.defaults() server.use(middlewares) server.use((req, res, next) => { if (isAuthorized(req)) { // add your authorization logic here next() // continue to JSON Server router } else { res.sendStatus(401) } }) server.use(router) server.listen(3000, () => { console.log('JSON Server is running') }) 复制代码
自定义输出
// In this example, returned resources will be wrapped in a body property router.render = (req, res) => { res.jsonp({ body: res.locals.data }) //res.jsonp => 包裹数据成json格式 //res.send => 直接发送字符串 } 复制代码
访问本应返回
{ "id": 21, "title": "长江", "date": "2016-09-12" } 复制代码
增加 body: res.locals.data后返回
{ body: { id: 1, title: "曹县宣布昨日晚间登日成功", date: "2016-08-12", likes: 55, views: 100086 } } 复制代码
终极Demo
访问 http://localhost:3000/echo
返回模拟数据
const jsonServer = require('json-server') const server = jsonServer.create() const router = jsonServer.router('db.json') const middlewares = jsonServer.defaults() let Mock = require('mockjs'); server.use(middlewares) var template = { 'titles': 'Syntax Demo', 'string1|1-10': '★', 'string2|3': 'value', 'number1|+1': 100, 'number2|1-100': 100, 'number3|1-100.1-10': 1, 'number4|123.1-10': 1, 'number5|123.3': 1, 'number6|123.10': 1.123, 'boolean1|1': true, 'boolean2|1-2': true, 'object1|2-4': { '110000': '北京市', '120000': '天津市', '130000': '河北省', '140000': '山西省' }, 'object2|2': { '310000': '上海市', '320000': '江苏省', '330000': '浙江省', '340000': '安徽省' }, 'array1|1': ['AMD', 'CMD', 'KMD', 'UMD'], 'array2|1-10': ['Mock.js'], 'array3|3': ['Mock.js'], 'function': function() { return this.titles } } server.get('/echo', (req, res) => { var data = Mock.mock(template) var json = JSON.stringify(data, null, 4) console.log('-----------------\n' + json) res.send(json) }) // To handle POST, PUT and PATCH you need to use a body-parser // You can use the one used by JSON Server server.use(jsonServer.bodyParser) server.use((req, res, next) => { console.log('--------------'+req.method) if (req.method === 'POST') { req.body.createdAt = Date.now() req.body.test = 1 } // Continue to JSON Server router next() }) // 返回错误码,和指定json格式的数据 //router.render = (req, res) => { // res.status(500).jsonp({ // error: "error message here" // "id": 21, // "title": "长江", // "date": "2016-09-12", // "likes": 509, // "views": 9900 // }) //} // Add this before server.use(router) server.use(jsonServer.rewriter({ '/api/*': '/$1', '/blog/:resource/:id/show': '/:resource/:id' })) router.render = (req, res) => { res.jsonp({ body: res.locals.data }) } server.use(router) server.listen(3000, () => { console.log('JSON Server is running') }) 复制代码
附录
json-server 命令参数
json-server index.js [options] <source> 选项: --config, -c Path to config file [默认值: "json-server.json"] --port, -p Set port [默认值: 3000] --host, -H Set host [默认值: "localhost"] --watch, -w Watch file(s) [布尔] --routes, -r Path to routes file --middlewares, -m Paths to middleware files [数组] --static, -s Set static files directory --read-only, --ro Allow only GET requests [布尔] --no-cors, --nc Disable Cross-Origin Resource Sharing [布尔] --no-gzip, --ng Disable GZIP Content-Encoding [布尔] --snapshots, -S Set snapshots directory [默认值: "."] --delay, -d Add delay to responses (ms) --id, -i Set database id property (e.g. _id) [默认值: "id"] --foreignKeySuffix, --fks Set foreign key suffix (e.g. _id as in post_id) [默认值: "Id"] --quiet, -q Suppress log messages from output [布尔] --help, -h 显示帮助信息 [布尔] --version, -v 显示版本号 [布尔] 示例: index.js db.json index.js file.js index.js http://example.com/db.json https://github.com/typicode/json-server Missing <source> argument 复制代码
以上所述就是小编给大家介绍的《自建-模拟JSON REST API-从入门到精通-前端必备技能-你还在等你后台API吗?》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- [ Laravel从入门到精通 ] 测试系列 —— 通过测试驱动开发构建待办任务项目(二):前端功能和浏览器...
- 圣思园《精通Spring Boot/Cloud》与《精通Java并发》课程现已宣布
- Charles 从入门到精通
- MAT 入门到精通(一)
- Git 从入门到精通
- Webpack入门到精通(1)
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Web性能权威指南
Ilya Grigorik / 李松峰 / 人民邮电出版社 / 2013-9 / 69
本书是谷歌公司高性能团队核心成员的权威之作,堪称实战经验与规范解读完美结合的产物。本书目标是涵盖Web 开发者技术体系中应该掌握的所有网络及性能优化知识。全书以性能优化为主线,从TCP、UDP 和TLS 协议讲起,解释了如何针对这几种协议和基础设施来优化应用。然后深入探讨了无线和移动网络的工作机制。最后,揭示了HTTP 协议的底层细节,同时详细介绍了HTTP 2.0、 XHR、SSE、WebSoc......一起来看看 《Web性能权威指南》 这本书的介绍吧!