предисловие
В этой статье давайте реализуем интерфейс симуляции фиктивных данных и реализуем разделение фронтенда и бэкенда, чтобы нам не приходилось гоняться за бэкендом, чтобы сильно нуждаться в интерфейсе~
развивать
Давайте кратко представим пакеты, которые мы используем:
имя | Введение |
---|---|
koa | Простой и удобный веб-фреймворк. Для него характерна элегантность, простота, выразительность и свобода. |
koa-router | Обычно используемая библиотека маршрутизации koa |
koa-bodyparser | Промежуточное ПО для разбора тела |
mockjs | Генерация случайных данных, моделирование данных |
Давайте установим эти пакеты
npm install -D koa koa-router koa-bodyparser mockjs
Помните нашу структуру каталогов на предыдущей картинке, давайтеmock
создать папкуmock-server.js
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 должен соответствовать порту devServer в webpack.
Затем мы создаемhome.js
, давайте сначала воспользуемся примером, приведенным в фиктивной документации
// 使用 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
Скрипты добавляют команду запуска
"mock": "node ./mock/mock-server.js"
Хорошо, давайте выполним командную строкуnpm run mock
, см. вывод командной строкиapp started at port 3000
Указывает, что запуск прошел успешно. Мы можем инициировать запрос, чтобы увидеть, есть ли смоделированные данные в нашем home.js.
Я использую fetch, чтобы инициировать запрос, конечно, есть много способов, не обязательно таких же, как у меня.
npm install whatwg-fetch -S
впусти насHome.jsx
Добавьте код внутрь:
import React, {PureComponent} from 'react'
export default class Home extends PureComponent{
componentDidMount(){
fetch('api/list')
}
render(){
return (
<div>Hello World!</div>
)
}
}
Хорошо, теперь давайте выполним в новой командной строкеnpm start
Запустите проект. Проверьте в браузере, есть ли запрос списка отправленных и возвращенных данных.
Давайте изменимся сейчасhome.js
Симулируя данные, мы обнаружим, что возвращаемые данные запроса не изменились, и нам нужно перезапустить службу koa, что очень хлопотно и не то, что мы хотим, так что же нам делать? позвольте мне установитьnodemon
давайте решим это
npm install -D nodemon
Исправлятьmock
Команда
"mock": "nodemon ./mock/mock-server.js"
бегатьnpm run mock
после модификацииhome.js
Попробуйте смоделированные данные, они идеальны?
Что ж, мы реализовали интерфейс симуляции фиктивных данных, но наш проект немного прост, давайте добавим несколько страниц и, кстати, инкапсулируем выборку.
существует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)
})
}
Это основано на пакете fetch antd-pro.
существует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')
Хорошо, теперь побегаем и посмотрим. Данные страницы 1 не изменяются, а данные страниц 2 и 3 генерируются случайным образом для каждого запроса.
Вы не чувствуете каждый раз, когда вы хотите много неприятностей в два раза в командную строку, чтобы начать ее? Конечно, мы можем интегрировать в команду, чтобы начать
npm install concurrently -D
Тогда мыpackage.json
Добавить новую команду запуска в скрипты
"dev": "concurrently \"npm run mock\" \"npm start\" "
Теперь мы можем использоватьnpm run dev
Команда для запуска.
Суммировать
В этой главе в основном представлена реализация интерфейса моделирования фиктивных локальных данных, а также добавлено несколько простых страниц в проект.
В следующей статье мы представим настройку среды разработки webpack.