应公司要求需要开发react,本文是自己刚刚学习react,需要快速了解项目上手开发的简单总结
项目结构简单介绍
我们主要关注src目录
public # 不参与编译的资源文件
node_modules #执行npm install 安装的依赖
src # 主程序目录common # 存放公用的js和less文件,less是css的升级,充当css的角色
components # 定义组件,比如询报比列表页的展示数据的表格
constant # 常量对象,基本就是后端的枚举类型,暂存提交审核等操作的动作码 在这定义
entry # 主要是一些js和less文件,是项目的入口
images # 图片文件
models # 这一层比较重要,后面详细介绍,询报比单据的基本属性被当做state数据都在这里定义
routes # 模仿mvc模式,将携带参数的一个叫做action的请求dispatch(派遣)到model层
service # 定义了向后端发送请求的函数
utils # 存放的都是js文件,定义了一些工具函数
Model
Model 是 dva 最重要的部分,可以理解为 redux、react-redux、redux-saga 的封装。
通常项目中一个模块对应一个 model,一个基本的 model 如下:
namespace 是该 model 的命名空间,同时也是全局 state 上的一个属性,只能是字符串,不支持使用 . 创建多层命名空间。
state 是状态的初始值。
reducer 类似于 redux 中的 reducer,它是一个纯函数,用于处理同步操作,是唯一可以修改 state 的地方,由 action 触发,它有 state 和 action 两个参数。
effects 用于处理异步操作,不能直接修改 state,由 action 触发,也可触发 action。它只能是 generator 函数(关于什么是generator函数,简单理解的话看这https://www.cnblogs.com/imwtr/p/5913294.html),并且有 action 和 effects 两个参数。第二个参数 effects 包含 put、call 和 select 三个字段,put 用于触发 action,call 用于调用异步处理逻辑,select 用于从 state 中获取数据。如果select时使用namespace的名字则获取全部state数据
subscriptions 用于订阅某些数据源,并根据情况 dispatch 某些 action,如上所示,监听路由变化,当进入 /user 页面时,dispatch一个type为fetch的action,这个action首先被effects 拦截,获取了user数据(获取user的yield是一个假方法,为了表述意思),随后执行put方法将一个type为save的action又发送到reducer中并发送user数据,然后reducer中的save方法将接收到的user赋值给state然后return,此处的return是将state数据return到一个叫store的空间中,它里面自动检测state的变化并在合适的时机渲染页面。
注意,在 model 中触发这个 model 中的 action 时不需要写命名空间,比如在 fetch 中触发 save 时是 { type: ‘save’ }。而在组件中触发 action 时就需要带上命名空间了,比如在某个组件中触发 fetch 时,应该是 { type: ‘user/fetch’ }。
connect
在routes层中有下面这个东西
connect的作用是将组件和models结合在一起。将models中的state绑定到组件的props中。并提供一些额外的功能,譬如dispatch
connect 方法返回的也是一个 React 组件,通常称为容器组件
connect 方法传入的第一个参数是 mapStateToProps 函数,该函数需要返回一个对象,用于建立 State 到 Props 的映射关系。
inquirySheetDetailModule 是一个model的命名空间,mapStateToProps函数返回这个命名空间的所有state数据,connect将这个state数据与当前的InquirySheetDetails组件连接
零碎知识点
无状态组件
正常我们定义组件是这样的
跟定义一个类差不多
还有通过React.createClass定义,就是下面这种,这种在我们的项目中少见,它与上面的区别可以见这http://www.cnblogs.com/wonyun/p/5930333.html
有时候在components目录下会发现这种东西
这其实就是定义了一个组件,它是一个无状态组件,也就是只展示数据也叫UI组件,是一种简化的写法
this的绑定
使用第一种方式React.Component 定义的组件中经常在构造函数里见到下面这种情况
this.后面的函数的确是在组件中定义的,就跟类中的成员函数或方法一样,但是组件跟类还是有区别的,当在其他组件中调用或是使用ReactDOM.render( )方法将其渲染到界面上时会生成一个组件的实例,因为组件是可以复用的,根据this指向的基本规则这里的this最终会指向组件的实例。组件实例生成的时候,构造器constructor会被执行,此处着重分析一下下面这行代码:
this.handleClick = this.handleClick.bind(this);
此时的this指向新生成的实例,那么赋值语句右侧的表达式先查找this.handleClick( )这个方法,由对象的属性查找机制(沿原型链由近及远查找)可知此处会查找到原型方法this.handleClick( ),接着执行bind(this),此处的this指向新生成的实例,所以赋值语句右侧的表达式计算完成后,会生成一个指定了this的新方法,接着执行赋值操作,将新生成的函数赋值给实例的handleClick属性,由对象的赋值机制可知,此处的handleClick会直接作为实例属性生成。总结一下,上面的语句做了一件这样的事情:
把原型方法handleClick( )改变为实例方法handleClick( ),并且强制指定这个方法中的this指向当前的实例。
实例
这个实例可以帮助快速理清数据流转的逻辑
https://www.jianshu.com/p/e184cd6d253c