通过三张图了解Redux中的重要概念
上周利用业余的时间看了看Redux,刚开始有点不适应,一下在有了Action、Reducer、Store和Middleware这么多新的概念。
经过一些了解之后,发现Redux的单向数据里的模式还是比较容易理解的,结合着Redux的单向数据流模型,很多概念就比较清晰了。
下面就按照自己的理解整理出了Redux中相关的内容,如果你也刚开始学习Redux,希望能给你一个直观的认识。
Action/Reducer/Store
首先,先看看第一张图,图中展示了Redux的单向数据流,以及Action、Reducer和Store这三个核心概念。
下面就围绕上图,非别介绍Action、Reducer和Store这三个概念。
Action和Action Creator
Action是一个对象,用来代表所有会引起状态(state)变化的行为(例如服务端的响应,页面上的用户操作)。
假如我们要实现一个任务管理系统,那么添加任务的Action对象就会是下面的形式:
{
type: 'ADD_TASK',
name: 'Read ES6 spec',
category: 'Reading'
}
Action对象是行为的描述,一般都会包含下面的信息:
- 一个字符串类型的type字段来表示将要执行的动作
- 需要传递给应用的其他数据信息(例子中的name和category),数据形式用户可以自定义
Action通过Action创建函数(Action Creator)来创建,Action Creator是一个函数,最终返回一个Action对象。
对于添加任务这个行为,对应的Action Creator如下:
function addTask(name, category) {
return {
type: ADD_TASK,
name,
category
};
}
Reducer
Action对象仅仅是描述了行为的相关信息,至于如何通过特定的行为来更新state,就需要看看Reducer了。
关于Reducer,最简单的描述就是:
- Reducer是一个函数
- 该函数接收两个参数,一个旧的状态previousState和一个Action对象
- 返回一个新的状态newState
根据上面的描述,Reducer函数就可以表示为:
(previousState, action) => newState
Reducer函数的形式通常如下:
function reducer(state = [], action) {
// 处理不同action的代码
switch (action.type) {
case SPECIAL_ACTION:
// 根据SPECIAL_ACTION action更新state
// 返回新的state
default:
return state
}
}
Store
Actions描述了"what happened"的事实,Reducers则根据这些actions来更新state,而Store则是Actions和Reducers连接在一起的对象。
Store是Redux中数据的统一存储,维护着state的所有内容,所以Store的主要功能就是:
- 维护应用的state内容
- 提供getState()方法获取 state
- 提供dispatch(action)方法更新 state
- 提供subscribe(listener)方法注册监听器
看到Store提供的方法,就可以把Action、Reducer和Store联系在一起了:
- Store通过dispatch(action)方法来接收不同的Action
- 根据Action对象的type和数据信息,Store对象可以通过Reducer函数来更新state的内容
Middleware
下面就来看看第二张图,跟第一张图的差别不大,只是增加了中间件(Middleware)来处理Action。
在Redux中,Middlerwares主要的作用就是处理Action,Redux中的Action必须是一个plain object。但是为了实现异步的Action或其他功能,这个Action可能就是一个函数,或者是一个promise对象。这是就需要中间件帮助来处理这种特殊的Action了。
也就是说,Redux中的Middleware会对特定类型action做一定的转换,所以最后传给reducer的action一定是标准的plain object。
针对Action的特征,Reudx Middleware可以采取不同的操作:
- 可以选择传递给下一个中间件,如:next(action)
- 可以选择跳过某些中间件,如:dispatch(action)
- 或者更直接了当的结束传递,如:return。
Redux中常用的中间件:
- redux-thunk:action可以是一个函数,用来发起异步请求。
- redux-promise:action可以是一个promise对象,用来更优雅的进行异步操作。
- redux-logger:action就是一个标准的plain object,用来记录action和nextState的。
react-redux
经过前面的介绍,我们已经看到了Redux中的一些核心概念。Redux跟React没有直接的关系,本身可以支持React、Angular、Ember等等框架。
通过react-redux这个库,可以方便的将react和redux结合起来:react负责页面展现,redux负责维护/更新数据状态。
到这里,第三张图就展示了react-redux这个库的工作原理,react和redux是怎么联系到一起的。
react-redux中提供了两个重要功能模块Provider和connect,这两个模块保证了react和redux之间的通信,下面就分别看看这两个模块。
Provider
通过Provider的代码可以看到,Provide本质上是一个react组件。
export default class Provider extends Component {
getChildContext() {
return { store: this.store }
} constructor(props, context) {
super(props, context)
this.store = props.store
} render() {
const { children } = this.props
return Children.only(children)
}
}
Provider组件主要用到了react通过context属性,可以将属性(props)直接给子孙component,无须通过props层层传递,从而减少组件的依赖关系。
connect
connect方法的主要作用就是让Component与Store进行关联, Store的数据变化可以及时通知Views重新渲染。
任何一个通过connect()函数处理过的组件都可以得到一个dispatch方法作为组件的props,以及得到全局state中的所有内容。
通过源码]可以看到,connect函数运行后,会返回一个wrapWithConnect函数,该函数可以接收一个react组件,然后返回一个经过处理的Connect组件。
return function wrapWithConnect(WrappedComponent) {
class Connect extends Component {
constructor(props, context) {
// 从祖先Component处获得store
this.store = props.store || context.store
this.stateProps = computeStateProps(this.store, props)
this.dispatchProps = computeDispatchProps(this.store, props)
this.state = { storeState: null }
// 对stateProps、dispatchProps、parentProps进行合并
this.updateState()
}
shouldComponentUpdate(nextProps, nextState) {
// 进行判断,当数据发生改变时,Component重新渲染
if (propsChanged || mapStateProducedChange || dispatchPropsChanged) {
this.updateState(nextProps)
return true
}
}
componentDidMount() {
// 改变Component的state
this.store.subscribe(() = {
this.setState({
storeState: this.store.getState()
})
})
}
render() {
// 生成包裹组件Connect
return (
<WrappedComponent {...this.nextState} />
)
}
}
Connect.contextTypes = {
store: storeShape
}
return Connect;
}
详细内容和demo
文中很多Redux的概念都是进行了简单的介绍,更多详细的介绍可以参考我整理的内容,GitHub地址:WilberTian/StepByStep-Redux
- 01.Action.md
- 02.Reducer.md
- 03.Store.md
- 04.Redux-data-flow.md
- 05.Middleware (part 1).md
- 05.Middleware (part 2).md
- 06.react-redux.md
每篇文章的结尾都会有一些简单的demo 代码,帮助理解文章中介绍的内容。
总结
文中结合三张图片介绍了Redux中的一些核心概念,以及React和Redux之间通过react-redux这个库进行交互。
更多详细的内容,已经整理到了GitHub上了(WilberTian/StepByStep-Redux),通过这些介绍以及demo的运行结果,一定能对Redux有一个比较基本的认识。
所有的内容主要参考Usage with React,然后加上了自己的理解画了上面三张图,同时结合每个概念写了一些demo帮助理解。
通过三张图了解Redux中的重要概念的更多相关文章
- 三张图彻底了解Java中字符串的不变性
转载: 三张图彻底了解Java中字符串的不变性 定义一个字符串 String s = "abcd"; s中保存了string对象的引用.下面的箭头可以理解为"存储他的引用 ...
- 【转帖】自助式BI的崛起:三张图看清商业智能和大数据分析市场趋势
自助式BI的崛起:三张图看清商业智能和大数据分析市场趋势 大数据时代,商业智能和数据分析软件市场正在经历一场巨变,那些强调易用性的,人人都能使用的分析软件正在取代传统复杂的商业智能和分析软件成为市场的 ...
- 【转】一张图解析FastAdmin中的表格列表的功能
一张图解析FastAdmin中的表格列表的功能 功能描述请根据图片上的数字索引查看对应功能说明. 1.时间筛选器如果想在搜索栏使用时间区间进行搜索,则可以在JS中修改修改字段属性,如 {field: ...
- 三张图教你生成一个Android jar 库。
我看到非常多教人使用第三方开源组件的Android教程.都是在教基于源代码project的库导入,个人觉得非常不妥,觉得最恰当的方式是把源代码project生成一个jar再导入到目标project上使 ...
- 三张图让你高速明确activity与fragment生命周期的异同点
第一张图:activity的生命周期 第二张图:fragment的生命周期 第三张图:activity与fragment生命周期对照 补充:假设你还是不明确,请翻译一下你不理解的相应单词. ----- ...
- Redux中的重要概念
Action/Reducer/Store 首先,先看看第一张图,图中展示了Redux的单向数据流,以及Action.Reducer和Store这三个核心概念. 下面就围绕上图,非别介绍Action.R ...
- Dubbo的设计理念原来就藏在这三张图中
Dubbo在众多的微服务框架中脱颖而出,占据RPC服务框架的半壁江山,非常具有普适性,熟练掌握 Dubbo的应用技巧后深刻理解其内部实现原理,让大家能更好的掌控工作,助力职场,特别能让大家在面试中脱颖 ...
- 三张图搞懂JavaScript的原型对象与原型链
对于新人来说,JavaScript的原型是一个很让人头疼的事情,一来prototype容易与__proto__混淆,二来它们之间的各种指向实在有些复杂,其实市面上已经有非常多的文章在尝试说清楚,有一张 ...
- 三张图搞懂JavaScript的原型对象与原型链 / js继承,各种继承的优缺点(原型链继承,组合继承,寄生组合继承)
摘自:https://www.cnblogs.com/shuiyi/p/5305435.html 对于新人来说,JavaScript的原型是一个很让人头疼的事情,一来prototype容易与__pro ...
随机推荐
- 用div和css样式控制页面布局
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <m ...
- 学习 Mobile App 网站制作的11个优秀案例
我喜欢收集美丽的,精心设计的移动应用程序网站.在我看来,为 App 提供一个美丽的网站显示了设计者和开发者对它的用户和产品的关心,除了开发应用程序,他们去加倍努力去促进应用和传播关于它的 App. 我 ...
- .net学习之路——调试程序
没有人的程序是完美的,这条规则对所有的程序员来说也成立.没有人能在第一次就写出完美的程序来. 调试工具分为两类,一类是被动的,你等待它们告诉你问题:还有一类是主动的,允许你在程序运行时深入观察,并在逐 ...
- Spring(3)—— Junit框架单元测试
Junit主要用于单元测试,即白盒测试.它是一个开源的由JAVA开发的一个用于测试的框架. Junit的几个基本概念:TestCase,TestSuite,TestFixtrue TestCase:代 ...
- javascript的浅拷贝和深拷贝
1.浅拷贝:复制一份引用,所有引用对象都指向一份数据,并且都可以修改这份数据. 2.深拷贝(复杂):复制变量值,对于非基本类型的变量,则递归至基本类型变量后,再复制. 这里画一个简单的图来加深理解: ...
- Linux新手扫盲
一. Linux特点 1.免费/开源: 2.支持多线程/多用户: 3.安全性好: 4.对内存和文件管理优越. Linux最小只需4M ——> 嵌入式开发 二. 文件目录 Linux系统所有软硬件 ...
- WIFI热点
1.wifi热点是指把手机的接收GPRS.3G或4G信号转化为wifi信号再发出去,这样手机就成了一个WIFI热点. 2.手机必须有无线AP功能,才能当做热点.有些系统自带建热点这个功能比如IOS(比 ...
- 【读书笔记】iOS网络-理解错误源
考虑一个字节是如何从设备发往运程服务器以及如何从远程服务器将这个字节接收到设备,这个过程只需要几百毫秒时间,不过确要求网络设备都能正常工作才行.设备网络和网络互联的复杂性导致了分层网络的产生.分层网络 ...
- iOS--通讯录(UITableViewController)
本文主要实现通讯录的部分功能(分组名.索引.分组的组名)等等功能: 废话不多说了,先上效果图: 在工程中需要导入一个plist文件,文件图如图: 工程目录文件如图: 工程程序如图所示: RootTab ...
- iOS开发之UIAlertView与UIAlertController的详尽用法说明
本文将从四个方面对IOS开发中UIAlertView与UIAlertController的用法进行讲解: 一.UIAlertView与UIAlertController是什么东东? 二.我们为什么要用 ...