dva
是开发的 React 应用框架,将React-Router
,Redux
及异步操作Redux-saga
三个 React
工具库包装在一起,简化了 API
,让开发 React
应用更加方便和快捷。
数据变化的时机
数据的改变发生通常是通过用户交互行为或者浏览器行为(如路由跳转等)触发的,当此类行为会改变数据的时候可以通过 dispatch 发起一个 action,如果是同步行为会直接通过 Reducers 改变 State ,如果是异步行为(副作用)会先触发 Effects 然后流向 Reducers 最终改变 State,所以在 dva 中,数据流向非常清晰简明。
所以得出这个公式 =======》 dva = React-Router + Redux + Redux-saga
数据流模式
- 同步数据
- 异步数据
现在看看在dva里面怎么处理公共的数据仓库
实现效果
需要提醒的,项目已经安装好这三个工具,不用再安装。
核心概念
State
:一个对象,保存整个应用状态View
:React
组件构成的视图层Action
:一个对象,描述事件connect
方法:一个函数,绑定State
到View
dispatch
方法:一个函数,发送Action
到State
代码实现
- routes/IndexPage.js的逻辑
import React from "react";
import {
connect } from "dva";
import styles from "./IndexPage.css";
import PropTypes from "prop-types";
import {
Button, Space } from "antd";
function IndexPage(props) {
const {
username,
count,
addCount,
decCount,
addCountAsync,
minusCountAsync,
} = props;
return (
<div className={
styles.normal}>
<h1 className={
styles.title}>Yay! Welcome to dva!</h1>
<div className={
styles.welcome} />
<div className="demo-container">
{
username}
<p>{
count}</p>
<Space>
<Button onClick={
addCount} type="primary">
Add
</Button>
<Button type="primary" danger onClick={
decCount}>
Minus
</Button>
<Button onClick={
addCountAsync}>Add async 2s</Button>
<Button onClick={
minusCountAsync} danger>
Add async 2s
</Button>
</Space>
</div>
</div>
);
}
IndexPage.defaultProps = {
username: "admin",
count: 10,
};
IndexPage.propTypes = {
username: PropTypes.string,
count: PropTypes.number,
};
const matStateToProps = (state) => {
return {
count: state.products.count,
};
};
const mapDispatchToprops = (dispatch) => {
return {
addCount: () => dispatch({
type: "products/addCount" }),
decCount: () => dispatch({
type: "products/minusCount" }),
addCountAsync: () => dispatch({
type: "products/addCountAsync" }),
minusCountAsync: () => dispatch({
type: "products/minusCountAsync" }),
};
};
export default connect(matStateToProps, mapDispatchToprops)(IndexPage);
- models/products.js的逻辑
const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
export default {
namespace: "products",
state: {
count: 0,
lists: [
{
name: "dva", id: 1 },
{
name: "antd", id: 2 },
],
},
// 同步更新的方法
reducers: {
delete(state, {
id }) {
return {
...state,
lists: state.lists.filter((item) => item.id !== id),
};
},
addCount(state) {
return {
...state, count: state.count + 1 };
},
minusCount(state) {
return {
...state, count: state.count - 1 };
},
},
effects: {
// *addCountAsync(action, effects) {
// const { put, select, call } = effects;
// const data = yield select();
// console.log("我被点击了");
// yield call(delay, 2000);
// yield put({ type: "addCount" });
// },
// 设置不同类型的监听器,监听器类型有takeLatest, takeEvery, throttle, debounce
addCountAsync: [
function* (action, effects) {
const {
put, call } = effects;
yield call(delay, 2000);
yield put({
type: "addCount" });
},
{
type: "takeLatest",
},
],
*minusCountAsync(action, effects) {
const {
put, call } = effects;
yield call(delay, 2000);
yield put({
type: "minusCount" });
},
},
};
**注意:**effects里面的getor方法默认的监听模式是takeEvery
模式,也就是每次出发都会见听到,如下图
如果我们要更改模式,getor方法就要改写成如下
之前的,默认是takeEvery
*addCountAsync(action, effects) {
const {
put, select, call } = effects;
const data = yield select();
console.log("我被点击了");
yield call(delay, 2000);
yield put({
type: "addCount" });
},
特定的监听模式
addCountAsync: [
function* (action, effects) {
const {
put, call } = effects;
yield call(delay, 2000);
yield put({
type: "addCount" });
},
{
type: "takeLatest",
},
]
是不是很简单了,直接简化了之前单独引入三个工具库的代码,操作方便不少。
附上第二个实例的效果及代码 
- routes/Products .js
import React from "react";
import {
connect } from "dva";
import ProductList from "../components/ProductList";
const Products = (props) => {
const {
products, deleteProduct } = props;
return (
<>
<h2>List of Products</h2>
<ProductList onDelete={
deleteProduct} products={
products} />
</>
);
};
const mapStateToProps = (state) => {
return {
products: state.products.lists,
};
};
const mapDispatchToProps = (dispatch) => {
return {
deleteProduct: (id) => {
dispatch({
type: "products/delete", id });
},
};
};
export default connect(mapStateToProps, mapDispatchToProps)(Products);
- components/ProductList .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} rowKey="id" />;
};
ProductList.defaultProps = {
products: [],
};
ProductList.propTypes = {
onDelete: PropTypes.func.isRequired,
products: PropTypes.array.isRequired,
};
export default ProductList;
扫描二维码关注公众号,回复:
17524508 查看本文章
