dva
的model
数据层
dva
首先是一个基于redux
和 redux-saga
的数据流方案,简化开发体验,可以理解为是一个轻量级的应用框架,今天主要总结一下他的model
模块,这个模块我理解的是主要用来处理数据,就是所谓的数据层,model
主要包含五个部分
namespace
:命名空间state
:数据的初始化,优先级低于dva()
的opts.initialState
reducers
:同步更新state
,唯一可以更改state
的地方,通过action
触发effects
:异步更新state
,不直接修改state
,通过action
触发subscriptions
:订阅数据源(数据源可以是当前的时间,服务器的websocket
连接,keyboard
输入,geolocation
变化,history
路由变化等等),然后根据需要dispatch
相应的action
namespace
export default {
namespace: 'asn',
};
state
export default {
state: {
initdata:'我是初始值'
asnResult:null,
},
};
reducers
export default {
reducers: {
updateState(state, { payload }) {
return {
...state,
...payload,
};
},
},
};
effects
export default {
effects: {
*getAsnData({ payload }, { call, put }) {
// 其中Service.getAsnData是一个axios的请求,payload是请求的参数
// export function getAsnData(asnid) {
// return get(`/asns/summaries/${asnid}`);
//}
const { data = {} } = yield call(Service.getAsnData, payload.asnid);
yield put({
type: 'updateState',
payload:{
initdata:'初始值改变了',
asnResult:data
}
});
},
},
};
subscriptions
// 应用场景,比如当我进入某一个页面,然后发送一个ajax,除了在react的生命周期componentDidMount中去发送以外,还可以在subscriptions中通过监听路由的变化去dispacth一个action
subscriptions: {
sendAjax({ dispatch, history }) {
history.listen(({ pathname }) => {
if (pathname === '/asns') {
dispatch({
type: 'getAsnData',
});
}
})
},
keyEvent({dispatch}) {
key('⌘+up, ctrl+up', () => { dispatch({type:'add'}) });
}
}
model
是处理数据的地方,页面是应用数据的地方,那么如何把model
和page
连接起来,dva
提供connect
方法。这个 connect
就是 eact-redux
的 connect
。
下面案例的整个数据流向:
-
通过点击事件
getAsnData
,dispatch
一个action(asn/getAsnData)
触发effets
里面的getAsnData
方法 -
然后
effets
里面的getAsnData
方法通过yield call
去调用后端的接口Service.getAsnData
,拿到返回数据data
-
然后通过
reducer(updateState)
去更新state
-
最后页面通过命名空间
connect
连接到相应的model
,在通过this.props
拿到数据,展示在页面
import React from 'react';
import { connect } from 'dva';
import { Button } from 'antd';
// @装饰器模式
@connect(({ asn:{ asnResult },loading }) => ({
asnResult,
// dva-loading可以自动处理loading状态
asnloading:!!loading.effects['asn/getAsnData'],
}))
class ASN extends Component {
state = {}
getAsnData = () => {
const { dispatch } = this.props;
dispatch({
type: 'asn/getAsnData',
payload:{
asnid:xxxxxx
}
})
}
render() {
const { asnResult,asnloading } = this.props;
return(
<Button
onClick={this.getAsnData}
loading={asnloading}
>
获取asn的数据---->{asnResult}
</Button>
)
}
}
export default ASN
// 非装饰器模式
export default connect(({ asn:{ asnResult },loading }) => ({
asnResult,
// dva-loading可以自动处理loading状态
asnloading:!!loading.effects['asn/getAsnData'],
}))(ASN);
当然dva
中的数据流向不只上面异步一种,还有同步,以及通过监听某些数据源和行为,dva
官网用一张图把他的数据流转表达的非常清楚
如上图所示,不管通过同步异步还是其他,共同的都是通过dispatch
发起一个action
,如果是同步的那么直接走reducer
去改变state
,如果是异步的通过先触发effects
,再流向reducer
,最终去更新state
,还有一种是通过subscriptions
去监听某些数据源,然后dispatch
一个action