1,仅有 5 个 API,仅有5个主要的api
2,支持 HMR,支持模块的热更新。
3,支持 SSR (ServerSideRender),支持服务器端渲染
4,支持 Mobile/ReactNative,支持移动手机端的代码编写。
5,支持 TypeScript,支持TypeScript(它是JavaScript的一个超集,而且本质上向这个语言添加了可选的静态类型和基于类的面向对象编程)
6,支持路由和 Model 的动态加载。
import dav from 'dva-core'
//1.创建dva实例
const app=dva();
//2.装载插件(可选)
app.use(require('dva-loading')());
//3.注册model
app.model(require('./models/count'));
//4.配置路由
app.router(require('./router'));
//5.启动应用
app.start('#root');
在options可以配置所有的hooks
const app = dva({
history,
initialState,
onError,
onAction,
onStateChange,
onReducer,
onEffect,
onHmr,
extraReducers,
extraEnhancers,
});
这里比较常用的是,history的配置,一般默认的是hashHistory,如果要配置 history 为 browserHistory,可以这样:
import createHistory from 'history/createBrowserHistory';
const app = dva({
history: createHistory(),
});
关于react-router中的hashHistory和browserHistory的区别大家可以看:react-router。
initialState:指定初始数据,优先级高于 model 中的 state,默认是 {},但是基本上都在modal里面设置相应的state。
这里最常见的就是dva-loading插件的配置,
import createLoading from 'dva-loading';
...
app.use(createLoading(opts));
但是一般对于全局的loading我们会根据业务的不同来显示相应不同的loading图标,我们可以根据自己的需要来选择注册相应的插件。
export default {
namespace: 'app',
state: {
login: false,
loading: true,
fetching: false,
},
reducers: {
//保存app
updateState(state, { payload }) {
return { ...state, ...payload }
},
//添加app
add(state, { payload }) {
return [ ...state, payload ]
},
},
effects: {
//异步获取app,然后通过action保存
*fetch(action, { call, put }) {
const login = yield call(service.fetchApps)
yield put(type:'updateState',payload:apps);
}
}
}
modal是dva里面与我们真正进行项目开发,逻辑处理,数据流动的地方。这里面涉及到的namespace、Modal、effects和reducer等概念都很重要
一般都是这么写的
import { Router, Route } from 'dva/router';
app.router(({ history }) => {
return (
<Router history={history}>
<Route path="/" component={App} />
<Router>
);
});
启动应用,即将我们的应用跑起来。
初始值,我们在 dva() 初始化的时候和在 modal 里面的 state 对其两处进行定义,其中 modal 中的优先级低于传给 dva() 的 opts.initialState
// dva()初始化
const app = dva({
initialState: { count: 1 },
});
// modal()定义事件
app.model({
namespace: 'count',
state: 0,
});
action 的格式如下,它需要有一个 type ,表示这个 action 要触发什么操作;payload 则表示这个 action 将要传递的数据
{
type: String,
payload: data,
}
我们通过 dispatch 方法来发送一个 action
Action
Action 表示操作事件,可以是同步,也可以是异步
{
type: String,
payload: data
}
格式
dispatch(Action);
dispatch({ type: 'todos/add', payload: 'Learn Dva' });
具体可以查看文档:redux——action
model 是 dva 中最重要的概念,Model 非 MVC 中的 M,而是领域模型,用于把数据相关的逻辑聚合到一起,几乎所有的数据,逻辑都在这边进行处理分发
state
这里的 state 跟我们刚刚讲的 state 的概念是一样的,只不过她的优先级比初始化的低,但是基本上项目中的 state 都是在这里定义的。
namespace
model 的命名空间,同时也是他在全局 state 上的属性,只能用字符串,我们发送在发送 action 到相应的 reducer 时,就会需要用到 namespace 。
Reducer
以key/value 格式定义 reducer,用于处理同步操作,唯一可以修改 state 的地方。由 action 触发。其实一个纯函数。
Effect
用于处理异步操作和业务逻辑,不直接修改 state,简单的来说,就是获取从服务端获取数据,并且发起一个 action 交给 reducer 的地方。
其中它用到了redux-saga,里面有几个常用的函数。
*add(action, { call, put }) {
yield call(delay, 1000);
yield put({ type: 'minus' });
},
在项目中最主要的会用到的是 put 与 call。
RouteComponent
RouteComponent 表示 Router 里匹配路径的 Component,通常会绑定 model 的数据。如下:
import { connect } from 'dva';
function App() {
return <div>App</div>;
}
function mapStateToProps(state) {
return { todos: state.todos };
}
export default connect(mapStateToProps)(App);
我简单的分析一下这个图:
首先我们根据 url 访问相关的 Route-Component,在组件中我们通过 dispatch 发送 action 到 model 里面的 effect 或者直接 Reducer
当我们将action发送给Effect,基本上是取服务器上面请求数据的,服务器返回数据之后,effect 会发送相应的 action 给 reducer,由唯一能改变 state 的 reducer 改变 state ,然后通过connect重新渲染组件。
当我们将action发送给reducer,那直接由 reducer 改变 state,然后通过 connect 重新渲染组件。
这样我们就能走完一个流程了。
初识 Dva
Dva-React 应用框架在蚂蚁金服的实践
10分钟 让你dva从入门到精通
roadhog介绍
基于dva-cli&antd的react项目实战
作者:darrell
链接:https://www.jianshu.com/p/e184cd6d253c
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。