这篇咱们来实现mock数据模拟接口,实现先后端分离开发,不用在追着后端大大要接口了~javascript
先来简单介绍下咱们用到的包吧:java
名称 | 简介 |
---|---|
koa | 一种简单好用的 Web 框架。它的特色是优雅、简洁、表达力强、自由度高。 |
koa-router | 经常使用的 koa 的路由库 |
koa-bodyparser | 用来解析body的中间件 |
mockjs | 生成随机数据,模拟数据 |
让咱们来安装这些包吧node
npm install -D koa koa-router koa-bodyparser mockjs
复制代码
还记得咱们上一张的目录结构吧,让咱们在mock
文件夹下建立mock-server.js
react
const Koa = require('koa');
const router = require('koa-router')();
const bodyParser = require('koa-bodyparser');
const app = new Koa();
app.use(bodyParser())
const home = require('./home')
app.use(router.routes())
router.get('/list', async(ctx, next) => {
ctx.body = home
await next()
})
// error-handling
app.on('error', (err, ctx) => {
console.error('server error', err, ctx)
});
app.listen(3000); //这里的端口要和webpack里devServer的端口对应
console.log('app started at port 3000')
复制代码
注意哦, app.listen的端口要和webpack里devServer的端口对应webpack
而后咱们在建立一个home.js
, 让咱们先使用mock文档给的例子程序员
// 使用 Mock
var Mock = require('mockjs')
var data = Mock.mock( {
// 属性 list 的值是一个数组,其中含有 1 到 10 个元素
'list|1-10': [{
// 属性 id 是一个自增数,起始值为 1,每次增 1
'id|+1': 1
}]
})
module.exports = data
复制代码
而后咱们在package.json
的 scripts 添加启动命令web
"mock": "node ./mock/mock-server.js"
复制代码
好,让咱们执行命令行执行npm run mock
, 看到命令行输出app started at port 3000
说明启动成功了。咱们能够发起请求来看看是否是咱们home.js里面模拟数据。shell
我使用的是fetch来发起请求,固然办法有不少不必定要和我同样npm
npm install whatwg-fetch -S
复制代码
让咱们在Home.jsx
里面加入一些代码:json
import React, {PureComponent} from 'react'
export default class Home extends PureComponent{
componentDidMount(){
fetch('api/list')
}
render(){
return (
<div>Hello World!</div>
)
}
}
复制代码
好了,如今让咱们在新的命令行里面执行npm start
运行项目。在浏览器查看是否有list请求发出和返回数据。
如今让咱们修改home.js
模拟数据,咱们会发现请求的返回数据没有改变,须要重启koa的服务才能够,很麻烦,不是咱们想要的,那怎么办呢? 让我安装nodemon
来解决吧
npm install -D nodemon
复制代码
修改mock
命令为
"mock": "nodemon ./mock/mock-server.js"
复制代码
运行npm run mock
后,在修改home.js
的模拟数据试试,是否是很完美。
好了,mock数据模拟接口咱们已经实现了,不过咱们的项目有点简单,让咱们来加几个页面,顺便把fetch封装下吧。 在utils
文件夹下,建立request.js
import 'whatwg-fetch'
const codeMessage = {
200: '服务器成功返回请求的数据。',
201: '新建或修改数据成功。',
202: '一个请求已经进入后台排队(异步任务)。',
204: '删除数据成功。',
400: '发出的请求有错误,服务器没有进行新建或修改数据的操做。',
401: '用户没有权限(令牌、用户名、密码错误)。',
403: '用户获得受权,可是访问是被禁止的。',
404: '发出的请求针对的是不存在的记录,服务器没有进行操做。',
406: '请求的格式不可得。',
410: '请求的资源被永久删除,且不会再获得的。',
422: '当建立一个对象时,发生一个验证错误。',
500: '服务器发生错误,请检查服务器。',
502: '网关错误。',
503: '服务不可用,服务器暂时过载或维护。',
504: '网关超时。',
}
function checkStatus(response) {
if (response.status >= 200 && response.status < 300) {
return response
}
const errortext = codeMessage[response.status] || response.statusText
const error = new Error(errortext)
error.name = response.status
error.response = response
throw error
}
/** * * @param {string} url 请求url * @param {object} [options] fetch 配置选项 * @return {object} */
export default function request(url, options) {
const defaultOptions = {
credentials: 'include',
}
const newOptions = { ...defaultOptions, ...options }
if (newOptions.method === 'POST' || newOptions.method === 'PUT') {
if (!(newOptions.body instanceof FormData)) {
newOptions.headers = {
Accept: 'application/json',
'Content-Type': 'application/json; charset=utf-8',
...newOptions.headers,
}
newOptions.body = JSON.stringify(newOptions.body)
} else {
newOptions.headers = {
Accept: 'application/json',
...newOptions.headers,
}
}
}
return fetch(url, newOptions)
.then(checkStatus)
.then(response => {
if (newOptions.method === 'DELETE' || response.status === 204) {
return response.text()
}
return response.json()
})
.catch(e => {
const status = e.name
console.log(status)
})
}
复制代码
这里借鉴了antd-pro的fetch封装。
在routes
文件夹下,建立Page1.jsx Page2.jsx Page3.jsx
修改Home.jsx
为
import React, { PureComponent } from 'react'
import { Route, Switch, Redirect, Link } from 'react-router-dom'
import Page1 from './Page1.jsx'
import Page2 from './Page2.jsx'
import Page3 from './Page3.jsx'
export default class Home extends PureComponent{
render(){
return (
<div>
<div style={styles.container}>
<Link to="/page1" style={styles.link} >Page1</Link>
<Link to="/page2" style={styles.link} >Page2</Link>
<Link to="/page3">Page3</Link>
</div>
<div style={styles.container}>
<Switch>
<Route path="/page1" component={Page1}/>
<Route path="/page2" component={Page2}/>
<Route path="/page3" component={Page3}/>
<Redirect exact from="/" to='/page1' />
</Switch>
</div>
</div>
)
}
}
const styles = {
container: {
display: 'flex',
justifyContent: 'center'
},
link: {
marginRight: 10
}
}
复制代码
Page1.jsx
为:
import React, {PureComponent} from 'react'
import request from '../utils/request'
export default class Page1 extends PureComponent{
state={
data: {}
}
click=()=>{
request('api/page1').then(data=>{
this.setState({
data: data
})
})
}
render(){
return (
<div> <h1>Hello Page1!</h1> <input type="button" value="获取mcok" onClick={this.click} /> <div style={{width:300}}> <p>Page1的mock模拟数据为:{JSON.stringify(this.state.data)}</p> </div> </div> ) } } 复制代码
Page2.jsx
为:
import React, {PureComponent} from 'react'
import request from '../utils/request'
export default class Page2 extends PureComponent{
state={
data: {}
}
click=()=>{
request('api/page2').then(data=>{
this.setState({
data: data
})
})
}
render(){
return (
<div> <h1>Hello Page2!</h1> <input type="button" value="获取mcok" onClick={this.click} /> <div style={{width:300}}> <p>Page2的mock模拟数据为:{JSON.stringify(this.state.data)}</p> </div> </div> ) } } 复制代码
Page3.jsx
为:
import React, {PureComponent} from 'react'
import request from '../utils/request'
export default class Page2 extends PureComponent{
state={
data: {}
}
click=()=>{
request('api/page3').then(data=>{
this.setState({
data: data
})
})
}
render(){
return (
<div> <h1>Hello Page3!</h1> <input type="button" value="获取mcok" onClick={this.click} /> <div style={{width:300}}> <p>Page3的mock模拟数据为:{JSON.stringify(this.state.data)}</p> </div> </div> ) } } 复制代码
修改 mock
文件夹下的home.js
为mock.js
const router = require('koa-router')();
var Mock = require('mockjs')
router.get('/page1', async (ctx, next) => {
ctx.body = Mock.mock({
data: [
{
"id": 1,
"title": "科学搬砖组",
"description": '那是一种内在的东西,他们到达不了,也没法触及的',
},
{
"id": 2,
"title": "程序员平常",
"description": '那时候我只会想本身想要什么,从不想本身拥有什么',
},
{
"id": 3,
"title": "骗你来学计算机",
"description": '生命就像一盒巧克力,结果每每出人意料',
},
{
"id": 4,
"title": "全组都是吴彦祖",
"description": '但愿是一个好东西,也许是最好的,好东西是不会消亡的',
},
],
status: 200,
})
})
router.get('/page2', async (ctx, next) => {
ctx.body = Mock.mock({
"data|1-10":[{
'id|+1': 1,
'number|1-100': 10.0
}]
})
})
router.get('/page3', async (ctx, next) => {
ctx.body = Mock.mock({
"data|1-10":[{
'id|+1': 1,
'email': '@email',
'name' : '@Name'
}]
})
})
module.exports = router
复制代码
mock-server.js
修改成
const Koa = require('koa');
const router = require('koa-router')();
const bodyParser = require('koa-bodyparser');
const app = new Koa();
const mock = require('./mock');
app.use(bodyParser())
app.use(mock.routes())
// error-handling
app.on('error', (err, ctx) => {
console.error('server error', err, ctx)
});
app.listen(3000);
console.log('app started at port 3000')
复制代码
好,如今咱们在跑起来看看吧。page1的数据是不变的,page2和page3的数据每次请求都是随机生成的。
是否是感受每次要命令行启动两次很麻烦呢?咱们固然能够整合成一个命令来启动
npm install concurrently -D
复制代码
而后咱们在package.json
的 scripts 添加新启动命令
"dev": "concurrently \"npm run mock\" \"npm start\" "
复制代码
如今咱们就可使用npm run dev
一个命令来启动了。
本章主要介绍实现mock本地数据模拟接口,并对项目增长了些简单页面。
下篇文章咱们来介绍开发环境webpack的配置