最近在开发React技术栈的项目产品,对于数据状态的管理使用了Dva.js,作为一个资深的ow玩家,我看到这个名字第一反应就是————这不是ow里的一个女英雄吗?仔细阅读了官方文档之后,发现开发者还真是因为这个角色获得灵感,来命名这个数据状态管理插件,果然开发大佬都是工作和休闲两不误~
学过React的同学都知道它的技术栈非常多且杂,所以每当你使用React的时候都需要引入很多的模块,那么Dva就是把这些用到的模块集成在一起,比如一些需要引入的依赖react-saga/react-loger、必写的ReactDOM.render、provider、connect包裹等都省去不写,形成一定的架构规范,大大提高我们的开发效率
今天,就来写一份文档,帮助后续使用Dva的开发者更好得在实际项目中(PS:需要是以UMI为基础框架,纯Dva来构建项目可以直接看文章结尾的参考文档列表)上手使用
Dva首先是一个基于redux和redux-saga的数据流方案,然后为了简化开发体验,Dva还额外内置了react-router和fetch,所以也可以理解为一个轻量级的应用框架。
在我目前的项目中,更多是使用数据状态管理的功能,他在我司的fish框架中做了内嵌,在主流的React开发框架UMI中也做了内嵌适配,使用起来非常方便快速。
Dva设计的目的就是简化元素,降低难度,让你不用管他怎么实现的,我们按照默认的这个规则去写就可以
数据的改变发生通常是通过用户交互行为或者浏览器行为(如路由跳转等)触发的,当此类行为会改变数据的时候可以通过dispatch发起一个action,如果是同步行为会直接通过reducers改变states,如果是异步行为(副作用)会先触发effects然后流向reducers最终改变states

无论是Vue还是React开发,实际的大型应用一定有严格的分层开发规范,确保后续开发的可维护性,主要的分层结构有以下几点:
Dva中model就是做了这一层的操作model的命名空间,同时也是他在全局state上的属性.的方式创建多层命名空间,相当于这个model的keyconnect这个key将想要引入的model加入import { connect } from 'dva';
export default connect(({ namespaceValue }) => ({ ...namespaceValue }))(DvaCompoent);
model的状态数据immutable data来对待,保证每次都是全新对象,没有引用关系stateeffect。并且,每一次的计算都应该使用immutable dataeffect被称为副作用,在我们的应用中,最常见的就是异步操作subscription语义是订阅,用于订阅一个数据源,然后根据条件dispatch需要的actiondispatch是一个用于触发action的函数,action是改变state的唯一途径,但是它只描述了一个行为,而dipatch可以看作是触发这个行为的方式,reducer则是描述如何改变数据的Dva中,connect model的组件通过props可以访问到dispatch,可以调用model中的reducer或者effectsimport { connect } from 'dva';
const testCom = props => {
const { dispatch } = props;
const changeValue = (id, val) => {
// 调用reducer,一般是同步修改state中的值
dispatch({
type: 'dva/save',
payload: {
param: val
},
});
// 调用effect,一般是发送后台请求
dispatch({
type: 'dva/queryValue',
payload: {
id: id
},
});
};
return(
<div>'hello world'</div>
)
}
export default connect(({ dva }) => ({ ...dva }))(testCom);
需要注意的是:Effects里面的函数都是Generator函数
Generator函数自带的关键词,和*搭配使用,有点像async和await,使用*则表明它是Generator函数yield就是告诉程序这里是异步,需要等待这个后面的代码执行完成,同步代码可不使用该关键词dispatch传过来的payload同名参数Dva中Effects函数的固定传参model中state的数据,需要注意的是,state后面跟命名空间namespace的值const data = yield select((state) => state.namespaceName.valueName);
Dva中Effects函数的固定传参payload是参数,可以通过call来执行一个完整的异步请求,又因为yield的存在,就实现了异步转同步的方案const { data } = yield call(queryInterface, payload);
Dva中Effects函数的固定传参model中的Reducers或者Effects,通过Reducers来实现数据到页面的更新,也可以通过put实现Effects的嵌套使用yield put({
type: 'save',
payload: {
...payload
},
});
由于公司的fish框架以及常见的umi框架都对Dva做了深度继承,会默认将src/models下的model定义自动挂载,只需要在model文件夹中新建文件即可新增一个model用来管理组件状态,对于某个page文件夹下面的model也会默认挂载
├─assets `静态资源`
├─components `公共组件`
├─config `路由和环境配置`
├─constants `全局静态常量`
├─locale `国际化`
│ ├─en_US `英文配置`
│ └─zh_CN `中文配置`
├─models `全局数据状态` *Dva涉及的目录*
├─pages `页面目录,用我参与开发的其中一个目录来作为示例` *Dva涉及的目录*
│ ├─NodeConfig `NodeConfig示例目录`
│ │ ├─components
│ │ │ ├─Select `Select组件页面文件` *Dva涉及的目录*
│ │ │ │ └─components
│ │ │ │ ├─AudienceInfo
│ │ │ │ │ ├─index.js
│ │ │ │ │ └─index.less
│ │ │ │ ├─BlackList
│ │ │ │ │ ├─index.js
│ │ │ │ │ └─index.less
│ │ │ │ ├─ControlGroup
│ │ │ │ │ ├─index.js
│ │ │ │ │ └─index.less
│ │ │ │ └─GroupSelect
│ │ │ │ │ ├─index.js
│ │ │ │ │ └─index.less
│ │ │ │ ├─index.js
│ │ │ │ └─index.less
│ │ ├─models
│ │ │ ├─select.js `Select组件数据状态管理` *Dva涉及的目录*
│ │ └─services
├─services `全局接口配置`
├─themes `全局样式主题`
└─utils `js通用工具`
PS: 该树形图通过 `windows shell` 自带的 `tree` 命令生成
export default {
namespace: 'dva',
state: {
id: '',
value: {},
},
effects: {
// 所有effect前必须要加 *
*queryValue({ payload }, { select, call, put }) {
const params = {
id: payload.id ? payload.id : yield select(state => state.select.id)
}
const { data } = yield call(queryInterface, params); // queryInterface是定义好的后台请求接口,一般用axios或fetch来完成
yield put({ type: 'save', payload: data });
},
},
reducers: {
save(state, { payload }) {
return {
...state,
...payload,
};
},
},
subscriptions: {
keyboardWatcher({ dispatch }) {
key('⌘+up, ctrl+up', () => { dispatch( {type:'save'}) });
},
},
};
React的Connect函数是一种柯里化写法
import { connect } from 'dva';
const testCom = props => {
const { helloWorld = 'hello world'} = props;
return(
<div>{ helloWorld }</div>
)
}
// 绑定之后就可以在testCom组件中使用命名为dva的model了
export default connect(({ dva }) => ({ ...dva }))(testCom);
柯里化是把接受多个参数的函数转换成接受一个单一参数的函数(PS:Scala语言中也有类似的设计)
// 柯里化
var foo = function(x) {
return function(y) {
return x + y
}
}
foo(3)(4)
// 普通方法
var add = function(x, y) {
return x + y;
}
add(3, 4)
创建无状态组件是为了创建纯展示组件,这种组件只负责根据传入的props来展示,不涉及到要改变state状态的操作,
在实际项目中页面组件被写成无状态的组件,通过简单组合可以构建成页面或复杂组件,通过多个简单组件来合并成一个复杂的大应用
const NoStateComponent = props => {
const { helloWorld = 'hello world'} = props;
return(
<div>{ helloWorld }</div>
)
}
export default NoStateComponent;
无状态组件的优点
参考文档一 ———— Dva官方文档
参考文档二 ———— UMI官方文档
参考文档三 ———— REACT基础笔记 MODEL分层
参考文档四 ———— 前端数据流方案Dva
参考文档五 ———— 浅析dva (史上最全的dva用法及分析)
参考文档六 ———— 【dva】model中effects函数的解析
参考文档七 ———— Generator 函数的详解
参考文档八 ———— React connect()() 双括号 --柯里化写法
参考文档九 ———— 高级函数技巧-函数柯里化
我是 fx67ll.com,如果您发现本文有什么错误,欢迎在评论区讨论指正,感谢您的阅读!
如果您喜欢这篇文章,欢迎访问我的 本文github仓库地址,为我点一颗Star,Thanks~ ?
转发请注明参考文章地址,非常感谢!!!
有没有办法快速将表格格式的ruby哈希打印到文件中?如:keyAkeyBkeyC...1232343451253474456...其中散列的值是不同大小的数组。还是使用双循环是唯一的方法?谢谢 最佳答案 试试我写的这个gem(在表中打印散列、ruby对象、ActiveRecord对象):http://github.com/arches/table_print 关于ruby-如何以表格格式快速打印Ruby哈希值?,我们在StackOverflow上找到一个类似的问题:
我开始了一个新的Rails3.2.5项目,Assets管道不再工作了。CSS和Javascript文件不再编译。这是尝试生成Assets时日志的输出:StartedGET"/assets/application.css?body=1"for127.0.0.1at2012-06-1623:59:11-0700Servedasset/application.css-200OK(0ms)[2012-06-1623:59:11]ERRORNoMethodError:undefinedmethod`each'fornil:NilClass/Users/greg/.rbenv/versions/1
rails新手。只是想了解\assests目录中的这两个文件。例如,application.js文件有如下行://=requirejquery//=requirejquery_ujs//=require_tree.我理解require_tree。只是将所有JS文件添加到当前目录中。根据上下文,我可以看出requirejquery添加了jQuery库。但是它从哪里得到这些jQuery库呢?我没有在我的Assets文件夹中看到任何jquery.js文件——或者直接在我的整个应用程序中没有看到任何jquery.js文件?同样,我正在按照一些说明安装TwitterBootstrap(http:
我安装了ruby、yeoman,当我运行我的项目时,出现了这个错误:Warning:Running"compass:dist"(compass)taskWarning:YouneedtohaveRubyandCompassinstalledthistasktowork.Moreinfo:https://github.com/gruUse--forcetocontinue.Use--forcetocontinue.我有进入可变session目标的路径,但它不起作用。谁能帮帮我? 最佳答案 我必须运行这个:geminstallcom
我有一个包含多个组件的存储库,其中大部分是用JavaScript(Node.js)编写的,一个是用Ruby(RubyonRails)编写的。我想要一个.travis.yml文件来触发一个运行每个组件的所有测试的构建。根据thisTravisCIGoogleGroupthread,目前还没有官方支持。我的目录结构是这样的:.├──构建服务器├──核心├──扩展├──网络应用├──流浪文件├──package.json├──.travis.yml└──生成文件我希望能够运行特定版本的Ruby(2.2.2)和Node.js(0.12.2)。我已经有了一个make目标,所以maketest在每
电脑启动出现显示器黑屏是一个相当常见的问题。如果您遇到了这个问题,不要惊慌,因为它有很多可能的原因,可以采取一些简单的措施来解决它。在本文中,小编将介绍下面4种常见的电脑启动后显示器黑屏的原因,排查这些原因,快速解决! 演示机型:联想Ideapad700-15ISK-ISE系统版本:Windows10一、显示器问题如果出现电脑启动后显示器黑屏的情况。那么首先您需要检查一下显示器是否正常工作。您可以通过更换另一个显示器或将当前显示器连接到另一台计算机来检查显示器是否存在问题。如果问题仍然存在,那么您可以排除显示器故障的可能性。 二、显卡问题如果您的电脑配备了独立显卡,那么显卡故障也可能是导致电脑
文章目录一、项目场景二、基本模块原理与调试方法分析——信源部分:三、信号处理部分和显示部分:四、基本的通信链路搭建:四、特殊模块:interpretedMATLABfunction:五、总结和坑点提醒一、项目场景 最近一个任务是使用simulink搭建一个MIMO串扰消除的链路,并用实际收到的数据进行测试,在搭建的过程中也遇到了不少的问题(当然这比vivado里面的debug好不知道多少倍)。准备趁着这个机会,先以一个很基本的通信链路对simulink基础和相关的debug方法进行总结。 在本篇中,主要记录simulink的基本原理和基本的SISO通信传输链路(QPSK方式),计划在下篇记
我不是Ruby专家,但想弄清楚发生了什么,因为我试图让指南针在节点应用程序中工作,但我的Ruby似乎坏了。打字:ruby--version让我:ruby2.1.1p76(2014-02-24revision45161)[x86_64-darwin13.0]我安装了Homebrew,之前遇到过Ruby版本的问题,但它似乎已安装并且可以正常工作。但是,当我使用gem输入请求时,出现此错误:$gem-hErrorloadingRubyGemsplugin"/Users/user_dir/.rvm/gems/ruby-2.1.1@global/gems/executable-hooks-1.3
按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visitthehelpcenter指导。关闭9年前。多年来,我一直在使用多种语言进行编程,并且认为自己总体上相当擅长。但是,我从未编写过任何自动化测试:没有单元测试,没有TDD,没有BDD,什么都没有。我已经尝试开始为我的项目编写适当的测试套件。我可以看到在进行任何更改后能够自动测试项目中所有代码的理论值(value)。我可以看到像RSpec和Mocha这样的测试框架应该如何使设置和运行所述测试变得相当容易
我需要一些指导来了解如何将Angular整合到rails中。选择Rails的原因:我喜欢他们偏执的做事方式。还有迁移,gem真的很酷。使用angular的原因:我正在研究和寻找最适合SPA的框架。Backbone似乎太抽象了。我不得不在Angular和Ember之间做出选择。我首先开始阅读Angular,它对我来说很有意义。所以我从来没有去读过关于ember的文章。使用Angular和Rails的原因:我研究并尝试使用小型框架,例如grape、slim(是的,我也使用php)。但我觉得需要坚持项目的长期范围。我个人喜欢用Rails的方式做事。这就是我需要帮助的地方,我在Rails4中有