该篇文章适合的阅读人群:刚接手公司项目,技术栈为react,状态管理直接用的dva,但是不太了解redux、redux-saga、react-redux的人员,想要快速上手业务开发,看这篇就对了!
dva 首先是一个基于 redux 和 redux-saga 的数据流方案,然后为了简化开发体验,dva 还额外内置了 react-router 和 fetch,所以也可以理解为一个轻量级的应用框架。
// 引入接口方法用于在effects中编写所需的业务逻辑 import { queryCurrent } from '@/services/user' // 实际上只是按规则定义一个配置对象 const UserModel = { // 当前 Model 的名称。整个应用的 State,由多个小的 Model 的 State 以 namespace 为 key 合成 namespace: 'user', // 该 Model 当前的状态。数据保存在这里,直接决定了视图层的输出 state: { currentUser: {} }, // Action 处理器,处理异步动作,基于 Redux-saga 实现。Effect 指的是副作用。根据函数式编程,计算以外的操作都属于 Effect,典型的就是 I/O 操作、数据库读写。 effects: { // Effect 是一个 Generator 函数,内部使用 yield 关键字,标识每一步的操作(不管是异步或同步)。 *fetchCurrentUser({ payload, callback }, { call, put }) { // 执行异步函数 const response = yield call(queryCurrent) if(response.success) { const { user } = response if(callback) { callback(user) } // 发出一个 Action,类似于 dispatch yield put({ type: 'saveCurrentUser', payload: user }) } } }, // Reducer 是 Action 处理器,用来处理同步操作,可以看做是 state 的计算器。它的作用是根据 Action,从上一个 State 算出当前 State。 reducers: { saveCurrentUser(state, { payload = {} }) { return { ...state, currentUser: payload } } } } export default UserModel;
connect
连接上Dva并使用,如下代码:import { connect } from 'dva' const SetUserInfoComponent = props => { const { dispatch } = props // 1. 调用dva附加在组件props上的dispatch方法,发起一个action // 2. action是一个普通对象(plain object),一般包含type字段和payload字段(当然也可以视情况不传payload) dispatch({ // 3. type的值实际上类似一个寻址过程,编写规则即namespace/reducerName|effectName // 4. dva根据你的namespace去找到对应的model,根据你的reducerName|effectName找到对应的reducer或者effect // 5. 回到我们这个例子即:找到namespace为user的model,并触发一个名为fetchCurrentUser的effect,payload为空。 // 注意:实际上第5点描述的就是这个对象的键值对,这就是action,一个描述动作的普通对象。 type: 'user/fetchCurrentUser' }) } export default connect(({ user }) => ({ user }))(SetUserInfoComponent)
以下部分是详细说明:connect
是一个高阶函数,它接收一个mapStateToProps
函数(当然你也可以随便叫它什么名字,无非这个名字比较能阐明它的作用), 返回一个接收组件的函数。该组件增强函数是一个普通函数,接收组件,返回增强后的组件。使得增强后的组件可以在内部通过props
拿到dva中的state
、dva提供的dispatch函数
。
// connect第一个形参函数,描述了需要从全局state映射到组件props上的指定部分状态,该函数返回了一个对象内含状态键值对 const mapStateToProps = ({ user }) => ({ user }) connect(mapStateToProps)(Component) => <EnhancedComponent {...props, user: GlobalState[user], dispatch: fn(){/* dispatch function code*/}}/> //我们可以简单想一下connect的实现形式可能类似如下代码帮助理解 const connect = mapStateToPropsFunc => MetaComponent => { const state = mapStateToPropsFunc(dva.GlobalState) return <MetaComponent dispatch={dva.dispatch} {...state}/> }
实际上翻阅Dva源码可以知道connect方法就是由react-redux提供的(源码看这里),Dva做的工作就是引入导出connect便于我们统一在Dva中调用,即所谓的技术收敛。
请先阅读官网的这篇文章。