本系列文章主要整理于书籍《React状态管理与同构实战》。
本文推荐读者:菜鸟前端,初学前端者。
本文是对书籍的又一层整理,内容是在本人理解之后再次简略,相当于在前人咀嚼之后再咀嚼了,加之本人才疏学浅,
可能会(很大几率会)有一些描述不当的地方,希望同行前辈多多指正。
一、Redux应用架构基础
1、Redux是什么
React应用由组件构成其骨架,而状态 state 就是沟通骨架的血液。当项目越来越大时,组件之间的通信会变得更为频繁,此时组件之间的状态会变得更为复杂,这个时候需要有一种技术来对状态进行管理,而Redux就是这样的一种管理通信状态的技术。
1.1 Redux是库结合模式
- 按照官方定义
Redux is a predictable state container for Javascript apps,Redux是一个在JS中可以预测状态的容器。 - Redux 是一个库,同时它规定了开发者开发的方方面面,所以又像是一种设计模式,所以称
Redux是一个 严格规定了使用模式的库 - 作用:Redux 采用函数式编程思想,采用了单向数据流的理念,专注于全局状态的管理,为实现对数据状态的管理封装了很多方法,并且规定了我们管理的模式(如何管理,怎样管理)
1.2 React 与 Redux 之间的关系
- 它们之间没有必然联系。
- 但是当 React 项目越来越大时,对状态的关注与管理要求越来越高;而 Redux 能够 ”规范化“状态的改变,隐藏二者经常一同使用。
2、 Redux的设计哲学
2.1 Single source of truth
-
我们使用有且仅有的一个对象作为表述整个状态机的全部状态,并存储在 store 中,这个 store 就 React 组件以来的 “Single soure of truth”。
-
整个页面状态数据树被存储在一个对象中,会随着数据的变更而发生变化,任何时候我们都可以同过一下方法获取到数据状态:
let state = store.getState()
这样做的好处?
- 可以让我们聚焦于对这个对象的使用
- 页面的展示内容依赖于各个组件的状态数据
- 各个组件的状态数据依赖于一个存储在 store 中 JS 对象
- 这个对象可以通过
store.getState()获取
2.2 State is only read
- 页面状态数据书返回的结果是只读的
- 当我们需要新的数据状态时,会生成一个全新的状态数据树,使得 store.getState() 返回一个全新的对象。
- 这个生成新的状态数据树的过程如下:
- 当数据需要更新的时候, dispatch (派发)出一个 action(动作/事件)
- action 是一个JS对象,是用来描述这个动作单元变化的所有信息。
- Redux 会根据派发的信息进行一定的操作进而生产一个新的状态数据树
2.3 Changes are made with pure functions called reducer
当我们想要更改页面时,我们想到的是更改页面状态数据树中的状态,而状态数据树返回的对象是只读的,只能同 dispatch 派发出 action ,然后根据一些操作得到新的状态数据树,进而改变页面。
那么派发了 action 之后, Redux 的后续操作是如何创建出新的状态数据树呢?
- 使用
reducer函数接受 action ,然后执行状态数据树的变更。经过 reducer 函数处理之后, store.getState() 方法会返回新的状态数据树 - reducer 函数将根据原始状态数据树,结合描述改变信息 action ,生产一个新的页面状态数据树,并把它应用在 store.getState 中
对于 reducer 函数而言:
- Reducer 函数有两个参数,一个是传入的状态 preState,另外一个是描述改变信息的 action,返回的是一个新的状态 newState。
小结:
-
Redux追求单一数据源,所有状态都存储在 store当中,是一个对象。
-
状态数据是只读的,当页面需要作出改变的时候,这个改变由 action 进行描述,并由 dispatch 方法进行派发。
-
这个 action 被响应的 reducer 作为参数获取,并根据现有的页面状态数据树生产一个新的状态数据树。
-
结合 React, 当页面中各个 React 组件根据新的页面状态数据树抽取出自己需要的状态进行更新,并触发渲染后,就会得到我们预期的新的页面。
3、 函数式编程和纯函数
- 函数式编程是一种典型的声明式编程,与命令式编程相对立,它更看重的是执行的目的而不是执行过程。
- 函数可以与其它数据一样,作为参数传递,或者作为返回值返回,这体现了函数是 “第一公民”。
为什么 redux 会遵循函数式编程的理念,这样做有什么好处?
设想场景:当我们发现程序中存在一个bug,页面需要展示的是数据A,而我们现在展示的是数据B
-
出现的 state 是在 reducer 中产生的
-
产生这个state 是由于 reducer 接收了 action 这个描述状态改变的信息。
-
所以现在要看是 action 描述错误了,还是对应的 reducer 函数出现错误
-
而这就是 Redux 所拥有的可预测性,可追溯性——可以使得调试和维护代码更加简单。