今天正好在弄项目的ajax数据调用情况,趁热打铁记录下
1、创建一个对应的对象model、service、routes、mock作为一个简单的ajax的准备工作
/src/models/note.js
import { query } from '../services/note';
export default {
namespace: 'note',
state: {
foo:'open',
},
subscriptions: {
},
effects: {
*query({ payload }, { call, put }){
const { data } = yield call(query);
if(data.success) {
yield put({
type: 'querySuccess',
payload: {
foo: data.data[1],
}
})
}else{
alert(data.message);
}
},
},
reducers: {
// 使用服务器数据返回
querySuccess(state, action){
return {...state, ...action.payload, loading: false};
},
},
};
/src/routes/note.js
import React from 'react';
import { connect } from 'dva';
import { Button } from 'antd';
import { routerRedux } from 'dva/router';
function Note({dispatch,note}) {
const {
foo
} = note;
return (
);
}
export default connect(({note})=>({note}))(Note);
/src/services/note.js
import request from '../utils/request';
export async function query() {
return request('/api/notes');
}
/mock/note.js
'use strict';
module.exports = {
'GET /api/notes': function (req, res) {
setTimeout(function () {
res.json({
success: true,
data: ['foo', 'bar'],
});
}, 500);
},
};
2、注册路由和model
/src/router.js
import React from 'react';
import { Router, Route } from 'dva/router';
import IndexPage from './routes/IndexPage';
import Note from './routes/Note';
function RouterConfig({ history }) {
return (
"/" component={IndexPage} />
"/note" component={Note} />
);
}
export default RouterConfig;
/src/index.js
import dva from 'dva';
import './index.css';
import './index.html';
// 1. Initialize
const app = dva();
// 2. Plugins
// app.use({});
// 3. Model
app.model(require('./models/example'));
app.model(require('./models/note'));
// 4. Router
app.router(require('./router'));
// 5. Start
app.start('#root');
实现代码已经贴出,下面介绍下处理流程
项目启动访问http://localhost:8989/#/note 可以看到本测试页面只有一个按钮。
先介绍先当前页面的一个数据互通的过程页面和mode公用一个state
state: {
foo:'open',
},
ajax的作用就是刷新当前state的值
ajax的发起是由当前按钮发起, 实现的是按钮上的文字的转换
onClick={(value)=>{
dispatch({
type: 'note/query',
//这个位置的type对应是ajax发起的地址,对应的是model的effects中的一个方法,访问方法是modelName/methodName
payload: {
},
//payload 是用来承载请求参数的
})
}
}
下面来看model
effects: {
*query({ payload }, { call, put }){
const { data } = yield call(query);
//这个是没有任何参数的时候的写法
const { data } = yield call(query,parse(payload));
//这个是请求有参数的时候的写法
**以下是返回数据的处理过程**
if(data.success) {
yield put({
type: 'querySuccess',
//这个type对应的是reducers中的一个方法
payload: {
//在这个位置给state赋值
foo: data.data[1],
}
})
}else{
alert(data.message);
}
},
},
reducers: {
// 使用服务器数据返回
querySuccess(state, action){
//两种写法都是用来将服务器的数据刷新到页面中
return {...state, ...action.payload, loading: false};
return {...state, ...action.payload,total: action.payload.total loading: false};
},
},
下面再详细解释下call发起请求的部分
import { query } from '../services/note';
//这个query是对应的services中的一个方法,这个就是call发起请求的第一个参数,通过它对应的去service中寻找对应的ajax的请求
import request from '../utils/request';
//引入request工具包,这个是真正发起ajax的地方
export async function query() {
return request('/api/notes');
}
下面介绍下request
//service中发起的请求会在这个位置处理如果需要重写ajax的调用模式的话重写这个地方即可
export default function request(url, options) {
return fetch(url, options)
.then(checkStatus)
.then(parseJSON)
.then(data => ({ data }))
.catch(err => ({ err }));
}
这个位置曾经遇到的一个bug是请求发起的时候不会携带上cookie
解决方案
export default function request(url, options) {
let new_options = {
...options,
credentials: 'include',
headers: {
"Content-Type": "application/x-www-form-urlencoded"
}
};
return fetch(url, new_options)
.then(checkStatus)
.then(parseJSON)
.then((data) => ({ data }))
.catch(err => ({ err }));
}
至此一个ajax的请求就介绍完了