引言

最近工作需要用dva框架,同事帮我培训了一下,有一点点认识,在此总结。

当然,以后对dva可能会了解更透彻,文章会不断更新的。

 

初识

开始看架构代码,没有看文档的时候,不知道里面的几个关键字是什么意思:

  1. Effect
  2. Reducer
  3. Dispatch
  4. mapStateToProps
  5. NAMESPACE

一头雾水,感觉好复杂。听完同事讲解以后,觉得redux代码量好大。

虽然公司其他项目用的不是这个框架,但是最近项目需要,没办法,学呗!

关于dva

dva 是基于现有应用架构 (redux + react-router + redux-saga 等)的一层轻量封装;

数据流向: 数据的改变发生通常是通过:

用户交互行为(用户点击按钮等)
浏览器行为(如路由跳转等)触发的
当此类行为会改变数据的时候可以通过 dispatch 发起一个 action ,如果是同步行为会直接通过Reducers 改变 State ,如果是异步行为(副作用)会先触发 Effects 然后流向 Reducers 最终改变State 。 所以在 dva 中,数据流向非常清晰简明,看最后思维导图。

关于Redux-saga

Redus-saga 是一个 redux 的中间件,主要用来简便而优雅的处理 redux 应用里的副作用(side effect相对于pure function这类概念而言的)。它之所以可以做到这一点主要是使用了ES6 里的一个语法: Generator 。使用 Generator 可以像写同步的代码一样编写异步代码,这样更加容易测试。(其实这里也不是特别懂,后面还要研究一下)

现在回头看(虽然才过去两天),感觉走了弯路。因为项目时间比较紧,同事跟我讲完,我想都没想,就按照他跟我说的逻辑,复制粘贴(在原来代码基础上),然后哪里报错修哪里。

后来越弄越搞不清楚。所以,拿到新东西,开始一定是看文档,看文档,看文档。

后来我看文档,把不懂的再确认一遍,看一下之前别人是怎么写的,然后从头开始写自己的任务:

1 添加路由(page)

2 添加布局以及组件

3 设计Model

4 connect关联

上手

下面根据以上四个步骤,我们来看一个用例

这个就是同事跟我讲解的时候写的,很清晰明了

step1:routes

这里没有写组件,如果有组件这里可以抽出来。

关于多层级组件传数据,我目前还不是完全明白,等后面搞明白了加上。

import React, { Component } from 'react'
import { connect } from 'dva'
import './index.less'
import { NAMESPACE } from '../../models/evaluateManage/constants';
import { Row , Col, Input, Button, Select } from 'antd'
const Option = Select.Option const mapStateToProps = (state) => ({
...state[NAMESPACE],
description: state[NAMESPACE].description,
menuList: state[NAMESPACE].menuList,
}) const mapDispatchToProps = (dispatch) => ({
dispatch,
updateState(val, cb){
dispatch({
type:`${NAMESPACE}/updateState`,
payload:{
params: val,
cb: cb
}
})
},
getMenu(val, cb){
dispatch({
type: `${NAMESPACE}/getMenu`,
payload: {
params: val,
cb: cb
}
})
}
}) @connect(mapStateToProps, mapDispatchToProps)
class EvaluateManage extends Component{ constructor(props){
super(props)
this.state = {
inputMsg: undefined
}
}
syncMethod = () => {
const { inputMsg } = this.state
this.props.updateState({
description: inputMsg
}, (res) => {
debugger
})
}
asyncMethod = () => {
this.props.getMenu({
tenantId: "_1RNSq2S"
})
}
asyncMethod = () => {
this.props.getMenu({
tenantId: "_1RNSq2S"
})
}
asyncMethodCallback = () => {
this.props.getMenu({
tenantId: "_1RNSq2S"
},(res = []) => {
this.props.updateState({
menuList: res,
description: "通过回调机制"
})
})
} inputMethod = (e) => {
let value = e.target.value
if(!value){
value = "我是描述"
}
this.setState({
inputMsg: value
})
} render(){
const { inputMsg } = this.state
const { menuList = [] } = this.props
return <div styleName="rule-wrapper">
<h1 styleName="ruleTitle">{this.props.description}</h1>
<h1 styleName="ruleTitle">我是输入内容:{inputMsg}</h1>
<Row>
<Col span={24}>
<Input onChange={this.inputMethod} value={inputMsg}/>
</Col>
</Row>
<Row>
<Col span={8}>
<Button size="large" onClick={this.syncMethod}>我是同步按扭</Button>
</Col>
<Col span={8}>
<Button size="large" onClick={this.asyncMethod}>我是异步按扭</Button>
</Col>
<Col span={8}>
<Button size="large" onClick={this.asyncMethodCallback}>我是异步按扭回调机制</Button>
</Col>
</Row>
<ul>
{
menuList.map((item) => {
const { name, code} = item
return <li>{name} {code}</li>
})
}
</ul> </div>
}
} export default EvaluateManage

  inistate

const evaluateManage = {
"description": "我是描述",
"menuList": []
}

  model

import * as constants from './constants'
import {initState} from "../initState";
import {apiCallTemplate} from 'Apis/api' export const getMenu = apiCallTemplate('getMenu', constants.NAMESPACE) export default {
namespace: constants.NAMESPACE,
state: initState[constants.NAMESPACE],
reducers: {
updateState(state, { payload }){
const { params, cb } = payload
cb && cb()
return {
...state,
...params
}
}
},
effects: {
*getMenu({ payload: {params = {},cb } }, { call, put}){
const { data } = yield call(getMenu, params)
const { menuList = [] } = data
if(cb){
cb(menuList)
}else{
yield put({
type: 'updateState',
payload: {
params: {
menuList,
description: "通过非回调机制"
}
}
})
} }
},
subscriptions: {},
}

 最终效果见下图

  点击同步按钮

  点击异步按钮,这里调了getMenu接口

异步和异步回调效果差不多的,后者多了回调

dva思维导图

写在最后

model中的reducers跟effects是负责修改状态state的方法,其中reducers是同步方法,effects是异步方法,reducers跟effects中的方法

组件中修改状态需要通过在Action中调用dispatch方法来调用reduces或effects中的方法来实现,

因此需要在组件中定义Action方法,页面根组件中的mapDispatchToProps里面负责定义Action,

所以在页面根组件中需要在mapDispatchToProps中定义操作reducers或effects的方法(action)

 

dva将所有与数据操作相关的逻辑集中放在一个地方处理和维护,在数据跟业务状态交互比较紧密的场景下,会使我们的代码更加清晰可控。

对于一个大型管理系统,由于要进行大量的数据操作,在设计model时将不同类型的业务需求数据操作分开处理,便于维护。

项目的开发流程一般是从设计 model state 开始进行抽象数据,完成 component 后,将组件和model 建立关联,通过 dispatch 一个 action ,在 reducer 中更新数据完成数据同步处理;

当需要从服务器获取数据时,通过 Effects 数据异步处理,然后调用 Reducer 更新全局 state 。

以上一个单向的数据流动过程。

解决了 redux 中代码分散和重写问题。

总之,Dva:Build redux application easier and better。

这里代码量确实比mobx的大,但这套框架也确实有可取之处。

阿里云主要用的语言是React,架构: Redux,框架:dva

备注:

react高阶组件学习

前端react迭代方向,尽量少用高阶组件,后期不好维护。多将组件细分,组件越小越好,类似乐高积木一样。

不过高阶组件还是要会运用。

Dva框架从初识到上手的更多相关文章

  1. 可靠通信的保障 —— 使用ACK机制发送自定义信息——ESFramework 通信框架4.0 快速上手(12)

    使用ESPlus.Application.CustomizeInfo.Passive.ICustomizeInfoOutter接口的Send方法,我们已经可以给服务端或其它在线客户端发送自定义信息了, ...

  2. VUE框架的初识

    VUE框架的初识 初步了解Vue.js框架(渐进式前端框架) Vue.js是一种轻量级的前端MVVM框架.同时吸收了React(组件化)和Angular(灵活指令页面操作)的优点.是一套构建用户界面的 ...

  3. dva框架使用详解及Demo教程

    dva框架的使用详解及Demo教程 在前段时间,我们也学习讲解过Redux框架的基本使用,但是有很多同学在交流群里给我的反馈信息说,redux框架理解上有难度,看了之后还是一脸懵逼不知道如何下手,很多 ...

  4. 在dva框架和create-react-app创建出来的框架中修饰器语法与按需加载引入antd分别配置

    按需加载需要的包  babel-plugin-import    装饰器语法需要的包  @babel/plugin-proposal-decorators dva框架 将.webpackrc  改成. ...

  5. dva框架使用mock.js模拟数据 + fetch请求数据

    what DVA? Dva是基于Redux做了一层封装,对于React的state管理,有很多方案,我选择了轻量.简单的Dva. dva 可以很方便就使用mock.js进行数据的模拟. 只需要三步,即 ...

  6. react的dva框架初试

    使用背景:迫不得已!!(自己入职是以vue技术入职的,说是马上vue项目就来了,让我负责这个项目的前端.但是入职后就让我下了现在这个项目看下,然后就顺理成章的帮忙进行开发了,其实自己一直想要做reac ...

  7. python的Web框架:初识Django

    web应用程序 本质 socket服务端 浏览器本质是一个socket客户端 1. 服务器程序 socket请求 接受HTTP请求,发送HTTP响应. 比较底层,繁琐,有专用的服务器软件,如:Apac ...

  8. Flask(1)- 主流web框架、初识flask

    一.Python 现阶段三大主流Web框架 Django.Tornado.Flask 对比 Django 主要特点是大而全,集成了很多组件(例如Models.Admin.Form等等), 不管你用得到 ...

  9. 使用dva框架的总结

    最近的项目是react+dva+atd+webpack的一个后台项目,刚接触dva就感觉很喜欢,很简洁用着很爽. 关于使用redux中的一些问题 1.文件切换问题. redux的项目通常哟啊分为red ...

随机推荐

  1. Anaconda安装PyTorch

    Anaconda是一个Python语言管理器,支持安装基于Python的开发包,例如tensorflow.Pytorch等,以及各种基于Python的IDE. https://www.jb51.net ...

  2. Apache配置详解(最好的APACHE配置教程)

    From: http://aiks.blog.com.cn/archives/2006/1748482.shtml Apache的配置 Apache的配置由httpd.conf文件配置,因此下面的配置 ...

  3. pyCharm报错"your evaluation license has expired, pycharm will now exit"解决方法(实测)

    一.修改C:\Windows\System32\drivers\etc 目录下的hosts文件 1.打开hosts文件,路径是 c:\windows\system32\drivers\etc\host ...

  4. iOS 自定义一对UI表现相反的按钮

    假如有一对按钮[重置][提交],要让他们的默认UI和点击的UI表现刚好相反 [提交]按钮,默认橙色,点击边框是橙色,字体是橙色,背景变白色 [重置]按钮,默认白色橙色,边框是橙色,点击字体是白色,背景 ...

  5. python调用c++/c 共享库,开发板上编译的一些坑!

    1.对于python,ctypes只能load动态库,但现在我的对象是一个静态库,而且我没有源代码,静态库在编译过程中没有加--fPIC参数,所以我也没办法将其编译为动态库,有没有什么方法在pytho ...

  6. EasyHook

    EasyHook实用指南 所谓实用指南就是全是干货,没那么多虚头巴脑的东西,真正要用的人会发现对自己有用的东西,浅尝辄止的人看起来会不知所云. FileMon自己实做的过程中遇到的问题: 1. exe ...

  7. 别把&和nohup混为一谈, 根本不是同一个东西好不好 ------ 聊聊./a.out & , nohut ./a.out , nohup ./a.out &的区别

    在第一家公司工作的时候, 我认识了&,在第二家公司工作的时候, 我认识了nohup,  这就是渊源.  随后, 我就一直糊涂用他们, 但并不懂这两个东西. 网上很多地方是乱扯, 瞎复制, 为什 ...

  8. RabbitMQ使用(上)

    1. 说明 在企业应用系统领域,会面对不同系统之间的通信.集成与整合,尤其当面临异构系统时,这种分布式的调用与通信变得越发重要.其次,系统中一般会有很多对实时性要求不高的但是执行起来比较较耗时的地方, ...

  9. LeetCode算法题-Magic Squares In Grid(Java实现)

    这是悦乐书的第326次更新,第349篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第196题(顺位题号是840).3 x 3魔方是一个3 x 3网格,填充了从1到9的不同 ...

  10. Tensorflow Learning1 模型的保存和恢复

    CKPT->pb Demo 解析 tensor name 和 node name 的区别 Pb 的恢复 CKPT->pb tensorflow的模型保存有两种形式: 1. ckpt:可以恢 ...