dva是基于redux
和redux-saga
的数据流方案,为了简化开发体验。内置了react-router
和fetch
是一个轻量级的框架。
特性
6个API,配合umi
使用降为0API
elm概念,通过reducers
,effect
和subscription
组织model
插件机制,dva-loading
自动处理loading状态,不用重复写 show 、hideLoading
HMR,基于 babel-plugin-dva-hmr
实现 components
,routes
,models
的HMR
dva-cli
npm install dva-cli -g
初始化
dav new 项目名
项目结构
项目名称
|
|--mock
|--public
|--src
| |-assets
| |-componets //UI组件
| |-models //管理修改状态
| |-routes //路由组件,切换路由展示的组件
| |-services //定义接口
| |-utils //使用fetch构建一个请求的工具
| |-index.js //要在这里载入model
| |-router.js //在routes创建了组件后要在这里引入
|
|--.webpackrc //webpack配置
Antd / 按需加载插件
npm install antd babel-plugin-import --save
npm install antd-mobile --save
配置 .webpackrc 文件
1.直接修改
Antd
{
"extraBabelPlugins": [
["import", { "libraryName": "antd", "libraryDirectory": "es", "style": "css" }]
]
}
Antd-mobile
{
"extraBabelPlugins": [
["import", { "libraryName": "antd-mobile", "style": "css" }]
]
}
2.拓展名改成.js
const path = require('path')
module.exports = {
"extraBabelPlugins": [
["import", { "libraryName": "antd-mobile", "style": "css" }]
],
alias:{
'@':path.resolve(__dirname,'./src'),
'components':path.resolve(__dirname,'./src/components'),
}
}
路由使用histyory模式
1) 终端中安装: npm install --save history
2) 在入口的src/ index.js中 导入
import {createBrowserHistory as createHistory} from "history"
3) 修改dva初始化内容 src/index.js中
const app =dva({history:createHistory()});
在routes 文件夹下创建 Product 组件(route component)
import React from 'react';
const Products = (props) => (
<h2>List of Products</h2>
);
export default Products;
把路由信息添加到路由表,编辑
router.js
import React from 'react';
import { Router, Route, Switch } from 'dva/router';
import IndexPage from './routes/IndexPage';
import ProductPage from './routes/ProductPage'
function RouterConfig({ history }) {
return (
<Router history={history}>
<Switch>
<Route path="/" exact component={IndexPage} />
<Route path="/product" exact component={ProductPage} />
</Switch>
</Router>
);
}
export default RouterConfig;
components 文件夹下创建js文件
import React from 'react';
import PropTypes from 'prop-types';
import { Table, Popconfirm, Button } from 'antd';
const ProductList = ({ onDelete, products }) => {
const columns = [{
title: 'Name',
dataIndex: 'name',
}, {
title: 'Actions',
render: (text, record) => {
return (
<Popconfirm title="Delete?" onConfirm={() => onDelete(record.id)}>
<Button>Delete</Button>
</Popconfirm>
);
},
}];
return (
<Table
dataSource={products}
columns={columns}
/>
);
};
ProductList.propTypes = {
onDelete: PropTypes.func.isRequired,
products: PropTypes.array.isRequired,
};
export default ProductList;
Dva 通过model 的概念把一个领域的模型管理起来,包含同步更新 state和reducers ,处理异步逻辑effects,订阅数据源 subscription
在model 文件夹中 创建文件
model/product.js
export default {
namespce:'product',
state:[],
reducers:{
'delete'(state,{payload:id}){
return state.filter(item => item.id !== id)
}
}
}
namespace
:表示在全局state上的keystate
:是初始值,在这里是空数组reducers
:等同于redux中的reducer,接收action
,同步更新 state
要在 index.js中载入这个文件
// 3. Model
app.model(require('./models/products').default);
dva提供了和redux一样的 connect 方法
import { connect } from 'dva';
使用
export default connect(({ products }) => ({
products,
}))(Products);
装饰器
@connect(({ products }) => ({
products,
}))
index.js设置
const app = dva({
initialState: {
products: [
{ name: 'dva', id: 1 },
{ name: 'antd', id: 2 },
],
},
});
通常数据改变发生在用户交互行为,或者浏览器的行为(路由的跳转),当数据发生改变的时候,会dispatch
一个action
,如果是同步的就直接通过reducers
去改变State
;如果是一个异步行为,就会通过触发effects
,然后流向reducers
,最终改变State
。
State
: 表示Model
的数据对象。在dva的实例属性上_store
看到顶部的state数据。Action
:改变State的唯一途径。通过dispatch
一个action
,action
必须带type
,其他字段可以自定义。dispatch
:在组件connect Model以后,通过props
传入,用于触发一个action
函数,调用到Model
中的Reducer
或Effects
,改变State
的唯一方式。dispatch
可以看做触发这个行为的方式。reducer
看做描述如何改变数据的。Reducer
: 聚合积累当前model
的state
对象,通过action
中的值,进行reducer
中的运算,获取最新的state,每一次计算都是immutable data
Effect
:副作用,也就是异步操作。底层是redux-saga
,是generator
的语法,异步转成同步写法。Subscription
:订阅。订阅一个数据源,依据条件dispatch
需要的action
。数据源可以是当前时间、websocket链接、keyboard输入、地理位置变化、路由变化等dva中提供了router的方法。使用的是react-router
import { Router, Route } from 'dva/router';
app.router(({history}) =>
<Router history={history}>
<Route path="/" component={HomePage} />
</Router>
);
routes文件夹下
其实就是Container Component
dva官方文档