概念
数据流向
当用户通过交互行为或者浏览器行为(路由跳转)改变数据时,可以通过dispatch发起一个action。如果是同步行为,直接通过reducers改变state,如果是异步行为,会先触发effects,然后流向reducers最终改变state。
Models
State
是一个js对象,操作的时候每次都要当做不可变数据来对待,保证每次都是全新对象,并且没有引用关系。这样才能保证state的独立性,便于追踪。state是存储数据的地方,收到action之后,会更新数据。
models/users.js
state:{
list:[],
total:null,
}
Action,Dispatch函数
是一个js对象,但是它只描述了一个行为,而 dispatch 可以看作是触发这个行为的方式,而 Reducer 则是描述如何改变数据的。所有的数据源都要通过dispatch函数调用一个action,从而改变对应的数据。action必须带有type属性,其他字段可以自定义。dipatch 可以看作是触发这个行为的方式,而 Reducer 则是描述如何改变数据的
注意dispatch是在组件connect Models以后,通过props传入的。
components/Users/Users.js
function createHandler(values){
dispatch({
type:'users/create', //如果在model外调用,需要添加namespace
payload: values, //需要传递的信息
})
}
Reducer
Reducer函数接收两个参数:当前model的state对象,和当前要被累积的值,返回的是一个新的累积结果。该函数把一个集合归并成一个单值。Reducer 必须是纯函数,所以同样的输入必然得到同样的输出,它们不应该产生任何副作用。
models/users.js
reducers:{
save(state,{payload:{data:list,total}}){
return {...state,list,total};
}
},
Effect
Effects是action处理器,用来处理异步操作。
call:执行异步函数,put:发出一个Action,类似于dispatch
models/users.js
effects:{
*fetch({payload:{page}},{call,put}){
const {data,headers} = yield call(usersService.fetch,{page});
yield put({type:'save',payload:{data,total:headers['x-total-count']}})
//total:从response header中获取total users数量
},
}
Subscription
是一种从源获取数据的方法,用于订阅一个数据源,然后根据条件dispatch需要的action。数据源可以是当前的时间、服务器的websocket连接、keyboard 输入、geolocation 变化、history 路由变化等等。
models/users.js
subscriptions:{
setup({ dispatch, history }) {
return history.listen(({ pathname, query }) => {
if (pathname === '/users') {
dispatch({ type: 'fetch', payload: query });
}
});
},
}
Routers
通常是指前端路由,dva 实例提供了 router 方法来控制路由,使用的是react-router。
index.js
app.router(require('./router'));
router.js
function RouterConfig({ history }) {
return (
<Router history={history}>
<Route path="/" component={IndexPage} />
<Route path="/users" component={Users} />
</Router>
);
}
Route Components
通常需要 connect Model的组件都是 Route Components,组织在/routes/目录下,而/components/目录下则是纯组件(Presentational Components)