dva框架的使用详解及Demo教程
在前段时间,我们也学习讲解过Redux框架的基本使用,但是有很多同学在交流群里给我的反馈信息说,redux框架理解上有难度,看了之后还是一脸懵逼不知道如何下手,很多同学就转向选择使用dva框架。其实dva框架就是一个redux框架与redux-saga等框架的一个集大成者,把几个常用的数据处理框架进行了再次封装,在使用方式上给使用者带来了便利,下面我们就来简单的介绍下dva框架的基本API和基本使用
Demo运行效果图
这里和讲解Redux框架一样,作者任然是提供了两个经典的Demo示例,CounterApp 和 TodoList 来帮助初学者更好的理解和使用
Demo地址
- CounterApp
https://github.com/guangqiang-liu/react-dva-counter
- TodoList
https://github.com/guangqiang-liu/react-dva-todoList
dva的由来
D.Va拥有一部强大的机甲,它具有两台全自动的近距离聚变机炮、可以使机甲飞跃敌人或障碍物的推进器、 还有可以抵御来自正面的远程攻击的防御矩阵。—— 来自 守望先锋 。
dva 官方地址
https://github.com/dvajs/dva/blob/master/README_zh-CN.md
dva核心API
- app = dva(opts)
创建应用,返回 dva 实例(注:dva 支持多实例)
opts
包含如下配置:
history
:指定给路由用的 history,默认是 hashHistoryinitialState
:指定初始数据,优先级高于 model 中的 state,默认是 {}
如果配置history
为 browserHistory,则创建dva对象可以写成如下写法
import createHistory from 'history/createBrowserHistory';
const app = dva({
history: createHistory(),
})
另外,出于易用性的考虑,opts 里也可以配所有的 hooks ,下面包含全部的可配属性:
const app = dva({
history,
initialState,
onError,
onAction,
onStateChange,
onReducer,
onEffect,
onHmr,
extraReducers,
extraEnhancers,
})
- app.use(hooks)
配置 hooks 或者注册插件。(插件最终返回的是 hooks )
比如注册 dva-loading
插件的例子:
import createLoading from 'dva-loading'
...
app.use(createLoading(opts))
hooks
包含如下配置项:
1、 onError((err, dispatch) => {})
effect 执行错误或 subscription 通过 done 主动抛错时触发,可用于管理全局出错状态
注意:subscription 并没有加 try…catch,所以有错误时需通过第二个参数 done 主动抛错
例子:
app.model({
subscriptions: {
setup({ dispatch }, done) {
done(e)
},
},
})
如果我们使用antd组件,那么最简单的全局错误处理通常会这么做:
import { message } from 'antd'
const app = dva({
onError(e) {
message.error(e.message, 3)
},
})
2、 onAction(fn | fn[])
在action被dispatch时触发,用于注册 redux 中间件。支持函数或函数数组格式
例如我们要通过 redux-logger 打印日志:
import createLogger from 'redux-logger';
const app = dva({
onAction: createLogger(opts),
})
3、 onStateChange(fn)
state
改变时触发,可用于同步 state 到 localStorage,服务器端等
4、 onReducer(fn)
封装 reducer 执行,比如借助 redux-undo 实现 redo/undo :
import undoable from 'redux-undo';
const app = dva({
onReducer: reducer => {
return (state, action) => {
const undoOpts = {};
const newState = undoable(reducer, undoOpts)(state, action);
// 由于 dva 同步了 routing 数据,所以需要把这部分还原
return { ...newState, routing: newState.present.routing };
},
},
})
5、 onEffect(fn)
封装 effect 执行。比如 dva-loading
基于此实现了自动处理 loading 状态
6、 onHmr(fn)
热替换相关,目前用于 babel-plugin-dva-hmr
7、 extraReducers
指定额外的 reducer,比如 redux-form
需要指定额外的 form reducer:
import { reducer as formReducer } from 'redux-form'
const app = dva({
extraReducers: {
form: formReducer,
},
})
- app.model(model)
注册model,这个操作时dva中核心操作,下面单独做详解
- app.unmodel(namespace)
取消 model 注册,清理 reducers, effects 和 subscriptions。subscription 如果没有返回 unlisten 函数,使用 app.unmodel 会给予警告⚠️
- app.router(({ history, app }) => RouterConfig)
注册路由表