父(外部)组件向子(内部)组件传递数据是经过自定义属性props值的方式进行实现的,而且在子组件内部经过this.props进行获取,它并不能直接被修改,若是想要修改,那么得经过React内置的一个setState的方法进行触发javascript
而子组件想要传递数据给父组件,是经过调用父组件的方法进行通讯前端
一个组件可能存在着不少状态,组件之间有时须要进行通讯,对于多个组件状态维护,若是依旧用原来的方式,那么就比较复杂了的java
那么Redux正好解决了这一问题.我的以为,Redux学起来很抽象,的确是块硬骨头,可是高山始终是要越过的web
下面就一块儿来学习下Redux的数据库
您将在本文中学习到数组
Redux是什么bash
Redux的使用场景以及与不使用Redux的灵魂对比服务器
Redux的工做流程架构
Redux的设计基本原则app
本篇虽不涉及代码层面上的,可是对后续编码Redux很是重要,磨刀不误砍柴工
若是想阅读体验更好,可戳连接,React进阶(1)-理解Redux
Redux是什么?
官方解释:JavaScript应用程序的可预测的状态容器(一个管理应用程序状态的框架)
通俗一点:管理组件公共数据状态的容器(仓库/区域)
解决的问题: 当应用组件拥有多个状态,而且组件之间须要共享数据状态时,从原始的组件传递数据的方式中解脱出来,集中管理组件的状态
你能够把Redux理解为一个仓库,房产中介.拥有不少共享的房源的一个管理者,后面会有具体的例子
Redux的使用场景
从上面提到的Redux解决问题能够看出,Redux只是用来管理和维护组件的状态的
React开发的模式就是组件化开发,将一个大的应用拆分红若干个小的应用,而后拼接成一个大的应用,而编写一个大小应用就是在编写各个大小组件
而组件的显示形态又取决于它的状态,这不区分于不管是外部的props仍是内部的state,而组件之间有时须要共享传递数据,Redux仅仅就是用来管理这些组件的状态的
在一些开发者眼里,项目里要是没有用到Redux,就以为很low,要么把Redux捧得高高在上,要么说都已经快0202年了,都用React hook了,鄙视得不行,我的以为彻底没有必要.
React与Redux自己就是解决两个不一样方向的问题,某种程度上讲,React能够视为MVC架构中的视图层V,而Redux则是model数据层M,而C层每每是链接视图层和model的链接器,每每处理前端数据请求,路由跳转等业务逻辑
即便不用Redux,照样能作小应用,只是略复杂繁琐一些而已,下面会介绍他们之间的对比
那么对于技术选型,何时用Redux何时不用?
如下是选用Redux的场景:
项目很是庞大,公共组件与业务组件很是多,用户的使用方式比较复杂
不一样身份的用户角色权限管理(例如不少后台管理系统,普通用户,超级管理员,VIP用户)读,写权限管理等
多个用户之间能够协做实时操做(不少那种在线敏捷协做办公文档工具,多个用户能够实时编辑操做同一份文档等的,例如石墨文档,语雀,confluence.钉钉等的)
须要与服务器大量的交互,或者使用了webscoket的,聊天,直播等应用的
视图层view须要从多个来源获取数据
....只要你发现React解决不了的问题,遇到多交互,多数据源的,那么就能够考虑使用Redux的
反之,则如下则是没有必要使用Redux
UI层很是简单,只是用于渲染,无复杂的数据交互,依赖外部的props就能够渲染组件
用户的使用方式比较简单,页面之间比较独立,没有互相协做
与服务器之间没有大量交互
当你发现使用React实在解决不了的问题,在各个组件之间传递数据很是复杂,很痛苦时,那么就能够考虑使用Redux了的,只要你hold住,没有所谓的高大上技术,只有适合本身业务的技术
盲目引入Redux只会增长项目的复杂度,引入新的技术应该是按部就班的
不使用Redux与使用Redux的灵魂对比
下面这张组件树状态图的对比就很好的解释了使用Redux与不使用Redux的区别
假设红色圆圈表明的是一个应用的子组件,若是想要把该红色圆圈组件的状态数据传递给父级或者非父级组件,它是经过调用父组件的方法来实现,这样一层一层往上传,若是组件树很庞大的话,那么就会变得很是繁琐
在小型项目中,Redux并非必需的,可是使用Redux倒是一劳永逸的,管理组件的状态方便得多,对于大型应用来讲,单纯使用原始的数据传递方式
那么组件之间的传值会变得很是复杂,若是要作一个大型的应用,那么就须要在React的基础上配置一个数据层的框架进行结合的使用
若是改成右边的Redux处理方式,将红色圆圈组件的状态数据放到一个Store仓库当中集中进行管理,哪一个组件须要的话,直接派发给哪一个组件就能够了的.
在Redux中,要求把组件的数据放到公共的存储仓库(区域)当中,让组件尽量的减小状态数据存储,换而言之,全部组件自身内部状态数据都不放在state里面了,把它放到Store这样的一个存储仓库当中去
其实本质上来讲,是放到reducer里面去管理,Store从Reducer中拿到返回的数据state,最后供外部组件的取用
当红色圆圈组件想要改变数据传递给其余组件时,只须要去改变Store里面的存储红色圆圈组件的数据就能够了
一旦Store公共存储的状态数据发生改变了的,因为其余组件是公用Store的数据,那么其余组件就会感知到Store的数据发生了改变,从而自身组件也会跟着改变
只要Store公共存储区域的数据发生改变,凡是共用了Store里面的数据的组件都会从新的取数据
这样一来,红色圆圈组件的数据就很是容易的传递给其余组件了,不管是它的父级组件仍是兄弟,非兄弟组件的
Redux就是把组件的数据放到一个公共的区域(仓库)中进行存储,当改变Store存储区域里面的数据时,其余组件若是用到了公共区域的数据,那么就会感知到数据的变化,它会自动的更新取Store中最新的数据
这样话,不管你的应用组件嵌套得有多么复杂,多么深,走的流程都是同样的,组件之间并不会干扰,低耦合的效果
当组件一修改,把修改的数据放到Store当中,而其余组件又从Store当中再来取,这样的话,组件与组件之间并非直接进行通讯的,是经过这么一个store中间角色来实现数据的传递共享的.
这样的话,组件的数据传递就简单多了的,也避免了组件与组件之间频繁通讯,容易产生混乱的问题
Redux实际上是Flux数据框架的一个替代演进,一样强调的是单向的数据源,保持状态只具有读的能力,而数据改变只能经过纯函数完成基本,这和原先中React的UI=render(data)彻底吻合.
React与Redux是两个独立的框架,前者是用于组件视图层的渲染,然后者是管理组件的数据
Redux的工做流程
如今已经知道了使用Redux与不使用Redux的区别,那么如今是时候来了解一下Redux的工做流程了,下面这个流程图对于理解Redux很重要 先附上一张Redux工做流的流程图:之后会在代码中逐步的体现
其中Store表明的就是负责组件存储全部公共状态的数据,全局只有一个Store.(这里你能够把它理解为相似生活当中中介公司管理房源的仓库(数据库)的区域经理)
实质上:store就是把Reducer关联到一块儿的一个对象,它提供dispatch(action)方法更新state,以及getState方法获取state
React Components:指的是页面上的任意一个组件(你能够理解为小区公寓楼里的每一个房间,而你就是住在里面的租房用户)
Actions Creators:具体要干什么事情,触发的动做,能够看作一个交互动做,改变应用状态或view的更新,都须要经过触发action来实现,Action的执行结果就是调用Dispatch来处理相应的事情,实现页面视图view的更新,惟一的办法就是调用dispatch派发action
它是一个javascript对象,是用来描述事件的行为的,对象里记录了相关的信息,例如:todolist的添加,删除list的这个具体操做,就是一个action
(当你想要提出换房的时候,跟中介公司管理房源的经理说,你要换个带有沙发,电视,配备厨房的两室一厅的房子,由于增长人口了,现有的房子住不下了的,你要作的什么事情,提出的条件信息就是数据),这个动做能够理解为actions creators
在你提出换房的时候,房产中介公司经理虽然手握不少房源,可是他也没有办法记得全部的房子相关信息,它须要去数据库(仓库)里去查,你经常看到中介小哥带你看房的时候
手上拿一个单子,Excel表格跟你介绍房源的时候,你能够把这个单子,Excel表格理解为一个实时记录本,只要有房子出租去了,这个表格就会实时更新(新旧信息的核实对比),返回一张新的房源信息表单给房产中介的经理
Reducer:能够把上面的用于实时更新记录房源信息的记录本称为Reducer,它只用做于根据旧的房源与提出新的需求(动做),老是会返回一张新的记录本给房产中介经理
实质上:Reducer是根据action发出的type(动做类型)来作什么事(返回最新的state给store等逻辑操做)
如今概括一下整个流程:
我(租客/组件React Component)想要换一个xxx信息的房子(Actions creators,具体要作的什么事情),房产中介经理收到了请求,他得根据你提供的一些需求信息去找相应的房源信息
可是房源太多,须要借助一个实时的记录本去查看符合条件的房源信息,当查到符合条件的信息后,这个记录本(Reducer)把最新的信息会返回给房产经理(Store),最终把信息返回给用户React Components,实现房子替换的更新
虽然文字啰嗦了点:可是Redux就是这么一回事,我要换大房子,房产中介经理听到后,它去记录本里面去查,查到以后,返回到房产中介经理,而后最终在返回给我,实现房子的替换
那么转换为代码理解:
页面上的一个组件,想要获取更新Store中的数据,跟Store说,我点击这个按钮,要更新这个组件的数据,要干什么事情,作的这个具体动做就是Actions Creators,这时会派发(dispatch) 该动做(action)给Store,Store会去Reducer里面去查一下,Reducer会返回一个新的结果给Store,Store拿到最新的数据结果后,返回给页面上的组件,实现页面组件的更新
你们能够先仔细体会上面这段文字的含义,在后续的实例代码中,在回过头来对比着代码与文字进行理解的,后续还会在拿出来的
Redux的设计基本原则
在Redux中有如下几个设计基本原则
单向数据流
惟一数据源
保持状态只读
数据的改变只能经过纯函数reducer来完成
单向数据流: 这个其实与props不能直接被修改同样,在父组件向子组件传递数据时是经过属性的方式进行传递的,而子组件内部经过this.props进行接收,可是外部传递过来的props属性不能直接被修改,若想要修改,须要借助React内置的setState方法进行触发
惟一数据源: 它指的是组件的应用状态数据应该只存在惟一的Store上,这一点是不一样于Flux的,在Flux中容许有多个store。而在Redux中整个组件的应用只保持一个Store,全部组件的数据源就是这个Store上的状态,能够将它Store理解为一个全局的变量对象
保持状态state可读: 不能直接的去修改状态,要修改Store的状态,必需要经过派发(dispatch)一个action对象去完成
而后组件渲染的对应的界面要更改的话,实际更改的就是组件的状态,若是状态都是只能读不能修改的话,那么界面就不会更新变化了
想要更改用户界面的渲染,就要改变组件的应用状态,但时改变组件状态的方法不是直接去修改状态上的值,而是建立一个新的状态对象返回给Redux,由Redux完成新的状态的组装
组件数据的改变只能经过纯函数完成
所谓的纯函数,就是指Reducer,而Redux某种程度上讲,它是Reducer+Flux的组合,其中这Redux的Red表明就是Reducer,而ux就是Flux,可是又不一样于Flux,它更像是Flux的一个实现,演进。它是为了描述Action如何改变组件的状态的
这也是为何Redux这个名称比较抽象的缘由,其中Reducer相似一个数组中的迭代器函数reduce
var arr = [1,2,3,4,5,6]
var sum = arr.reduce(function reducer(prevValue, currentValue,index,array){
console.log(`上一次调用回调返回的值(或者是提供的初始值): ${prevValue},数组中当前被处理的元素: ${currentValue}, 当前元素在数组中的索引: ${index}, 调用的数组: ${array}`);
return prevValue+currentValue;
},0)
console.log(sum); // 21
VM1742:3 上一次调用回调返回的值(或者是提供的初始值): 0,数组中当前被处理的元素: 1, 当前元素在数组中的索引: 0, 调用的数组: 1,2,3,4,5,6
VM1742:3 上一次调用回调返回的值(或者是提供的初始值): 1,数组中当前被处理的元素: 2, 当前元素在数组中的索引: 1, 调用的数组: 1,2,3,4,5,6
VM1742:3 上一次调用回调返回的值(或者是提供的初始值): 3,数组中当前被处理的元素: 3, 当前元素在数组中的索引: 2, 调用的数组: 1,2,3,4,5,6
VM1742:3 上一次调用回调返回的值(或者是提供的初始值): 6,数组中当前被处理的元素: 4, 当前元素在数组中的索引: 3, 调用的数组: 1,2,3,4,5,6
VM1742:3 上一次调用回调返回的值(或者是提供的初始值): 10,数组中当前被处理的元素: 5, 当前元素在数组中的索引: 4, 调用的数组: 1,2,3,4,5,6
VM1742:3 上一次调用回调返回的值(或者是提供的初始值): 15,数组中当前被处理的元素: 6, 当前元素在数组中的索引: 5, 调用的数组: 1,2,3,4,5,6
VM1742:6 21
复制代码
上面的代码中是作一个简单的累加,reducer函数接收四个参数,第一个参数是上一次调用返回的结果,第二个参数是当前被处理的元素的值,第三个是当前元素在数组中的索引,第四个是调用的原数组
这个reduce的方法接收一个函数做为累加器,reduce 为数组中的每个元素依次执行回调函数
而在Redux中,每一个reducer纯函数以下所示 其中reducer函数的第一个参数state是指当前的状态值,而第二个参数action是接收到的action对象
而reducer函数要作的事情就是根据state和action的值产生一个新的对象返回给Store,它是定义整个组件应用状态如何更改,根据Action动做行为去更新Store中的状态
注意的是reducer必须是纯函数,换句话说,reducer函数的返回结果必须彻底由参数state和action决定,并且不产生任何的反作用,也不能修改参数state和action对象
以下一个典型的reducer示例,reducer只是一个函数名称,你是能够任意取的,以下一个计数的counter纯函数
function counter(state = 0, action) {
switch (action.type) {
case 'INCREMENT':
return state + 1;
case 'DECREMENT':
return state - 1;
default:
return state;
}
}
复制代码
从上面的例子看得出,reducer函数不光接受action为参数,还接受state参数,也就是说,Redux中的reduce函数只负责计算组件的状态,却不负责存储组件的状态
在Reducer函数中每每包含action.type为判断条件的if-else或者switch语句,根据action,老是返回一个新的状态,这个新的状态的结果返回给store,store就会将原来上一次的state进行替换更新,最终达到改变state这么一个过程
本节主要介绍了Redux,它与React是两个独立的产品,两个框架作的事情的方向不同,React是用做于视图层的渲染,也至关于MVC中的V层,而Redux它是用于管理组件公共数据的Model层,更近一步讲,它是Reducer与Flux的一种结合,改进.
对比了使用Redux与不使用Redux的区别,以及Redux的工做流,最后Redux的设计基本原则,其中前两个,我的以为对于理解Redux是很是重要的
固然如今也可使用高阶组件,React hooks的写法,能够不用Redux了的,也有相似于dva这样的框架,基于Redux以及中间件(Redux-saga)的数据流方案
可是Redux依然是主流,只要你可以应付项目中开发需求,哪一个用得爽就用哪一个的,Redux虽然确实是绕了一些,有时候在各个文件之间进行来回切换,对于模块化的拆分,若是不是很清楚Redux的使用流程,不管是后续维护仍是迭代升级,都挺痛苦的
本篇并非什么高大上的内容,比较浅显,概念性的文字比较多,后续会结合具体的代码进一步理解Redux