dva内容简易了解
组件component
模型状态model
连接connect
使用
组件component
这个就不多说了,创建component的大家都会,配合umi来说的话就是在components文件文件夹中创建。
模型状态model
dva 通过 model 的概念把一个领域的模型管理起来,包含同步更新 state 的 reducers,处理异步逻辑的 effects,订阅数据源的 subscriptions 。
一个model大概如此:
export default { namespace: 'products', state: { ... }, effects: { *fun1({ payload }, { call, put, select }) { const data = yield call(接口_name, { 入参_obj }); yield put({type: 'save', payload: data }) const state = yield select(_ => _.products) ... }, *fun2({ payload }, { call, put, select }) {}, }, subscriptions: { setup({dispatch, history}) { history.listen(({pathname}) => { if (pathname === '/layouts' || pathname.indexOf('/layouts/') === 0) { //可在此时执行某异步effets,可以用于加载该路由页面组件一进入就需要的数据 dispatch({type: 'effects_name', payload: { obj }}); } }); }, }, reducers: { save(state, action) { return { ...state, ...action.payload, }; }, }, };
namespace,定义model的名字,一般与相关联的组件名一一对应。
state,作为这个model的状态。
effects,采用es6的Generator函数定义异步的方法,一般是用于请求接口,对应数据库的增删改查。
effects中有几个传入的方法call、put、select,一般都是先使用call进行接口的访问获取数据,使用put来执行reducers中的操作(通常是save)用获取来的数据更新state,select可以在effect中获取该model中当前的state,此处的products是model的namespace。
const data = yield call(接口_name, { 入参_obj }); yield put({type: 'save', payload: data }) const state = yield select(_ => _.products)
subscriptions,可以用于路由的监听:
subscriptions: { setup({dispatch, history}) { history.listen(({pathname}) => { if (pathname === '/layouts' || pathname.indexOf('/layouts/') === 0) { //可在此时执行某异步effets,可以用于加载该路由页面组件一进入就需要的数据 dispatch({type: 'effects_name', payload: { obj }}); } }); }, },
reducer,用于定义普通方法,比如用于修改state状态的函数,大多项目只需要一个save,也就是覆盖原state。
reducers: { save(state, action) { return { ...state, ...action.payload, }; }, },
连接connect
在组件中使用connect将component与model建立连接,通常一个component对应一个model,常见代码如下:
//普通组件 export default connect(({ model_namespace }) => ({ model_namespace }))(component_name); //需要路由跳转的组件 export default withRouter(connect(({ model_namespace }) => ({ model_namespace }))(component_name));
使用
model_namespace作为model的名称,也是这个model的state对象名称,它保存在该组件的props中,在组件中使用起来也很容易,在组件render函数return之前用解构赋值取出中model_namespace对象中的属性值,然后就可以使用了。
render(){ const { model_namespce : { data1, data2 } } = this.props return ... }
修改状态,也就是调用effects和reducers中的方法:
使用this.props上的dispatch,入参是一个对象,两个属性,一个type,一个payload。
type是由/分割的字符串,前面是model的namespace,后面是方法名,可以是effects中的异步方法也可以是reducers中的同步方法。
payload传入参数、新状态。
this.props.dispatch({ type: 'model_namespace/fun_name', payload: { count: 1 } });