我们都知道前端近几年发展速度非常快,当你还在舒适的CRUD-ING时,睁开眼已经是一个另一个世界,所以我必须得抬头看看这dva究竟是啥。
dva
基于redux
,redux-saga
和react-router
的轻量级前端框架。
为什么叫dva?
D.Va的机甲敏捷而强大-它的双核融合大炮会在短距离内用自动射击爆炸,并且她可以使用其助推器冲破敌人和障碍物,或者使用可清除弹丸的防御矩阵来攻击。
反正牛逼就是了。
是否支持IE8?
目前不支持。
想看看知道dva是怎么来的,还得回头看dva的前身——React + Redux最佳实践
未来简化使用redux和redux-saga时很多繁琐的操作,开发者基于此最佳实践做了一个封装方案:dva
我们都知道前端近几年发展速度非常快,当你还在舒适的CRUD-ING时,睁开眼已经是一个另一个世界,但无论它怎么变都离不开核心的几个概念:
URL
我得知道改访问什么页面Data
为了显示信息View
这个页面长成什么样子Action
对页面的操作API Server - Data
数据的来源
下面简要的描述一下这5个方面
URL -> Data
需求:routing
选择:react-router
+ react-router-redux
(前者是业界标准,后者可以同步route信息到state,这样可以在view根据route信息调整展现,以及Action来修改route)
Data
需求:为redux提供数据源,修改容易
方案:plain object
配合combinReducer
Date -> View
需求:数据的过滤和筛选
方案:store和select
,用于提取数据的筛选逻辑,让Component保存简单。
Action <> Store 业务逻辑处理
需求:统一处理业务逻辑,尤其是异步的处理
方案:redux-saga
用于管理action,处理异步逻辑
于是…就有了下面这张图:
Dva的目的
聊完dva的前身,dva的出生就很明确了。
为了更轻松,更好地构建redux应用程序
第一印象
import dva from 'dva' ;
//创建dva实例
const app = dva();
//装载插件
app.use(require('dva-loading')());
//注册Model
app.model(require('/models/count'));
//配置路由
app.router(require('./router'));
//启动应用
app.start('#root');
dva特性
- 仅有5个API
- 支持HMR
- 支持SSR
- 支持移动/ReactNative
- 支持TypeScript
- 支持路由和模型的动态加载
- 完善的语法分析库dva-ast
挂钩和插件
- onError( fn,调度 )
- onAction( fn | fn[] )
- onStateChange ( fn )
- onReducer( fn )
- onEffect ( fn )
- onHmr ( fn )
dva加载
import createLoading from 'dva-loading';
const add = dva ();
app.use(createLoading(opts));
function mapStateToProps(state,ownProps){
return {
loading:state.loading.global,
...listSelector(state,ownProps),
};
}
export default connect(mapStateTpProps)(ListPage);
错误捕获
import {message) from 'antd';
const ERROR_MSG_DURATION = 3; //3秒
const app = dva ({
onError(e){
message.error(e.message,ERROR_MSG_DURATION);
},
})
错误触发
*a(){
throw new Error('a error');
}
举个栗子:计数器
import React from 'react';
import dva, { connect } from 'dva';
import './style.css';
// 1. Initialize
const app = dva();
console.log(2);
// 2. Model
app.model({
namespace: 'count',
state: 0,
reducers: {
add (count) { return count + 1 },
minus(count) { return count - 1 },
},
});
class TestError extends React.Component {
componentDidCatch(e) {
alert(e.message);
}
componentDidMount() {
// throw new Error('a');
}
render() {
return <div>TestError</div>
}
}
// 3. View
const App = connect(({ count }) => ({
count
}))(function(props) {
return (
<div>
<TestError />
<h2>{ props.count }</h2>
<button key="add" onClick={() => { props.dispatch({type: 'count/add'})}}>+</button>
<button key="minus" onClick={() => { props.dispatch({type: 'count/minus'})}}>-</button>
</div>
);
});
// 4. Router
app.router(() => <App />);
// 5. Start
app.start('#root');