什么是redux?
Redux官方文档对Redux的定义:Redux是针对JavaScript应用的可预测状态容器。包含了以下几个含义:
1:可预测性(predictable): 因为Redux用了reducer与纯函数(pure function)的概念,每个新的state都会由旧的state建来一个全新的state。因而所有的状态修改都是”可预测的”。
2:状态容器(state container): state是集中在单一个对象树状结构下的单一store,store即是应用程序领域(app domain)的状态集合。
3:JavaScript应用: 这说明Redux并不是单指设计给React用的,它是独立的一个函数库,可通用于各种JavaScript应用。
可以让你构建一致化的应用,运行于不同的环境(客户端、服务器、原生应用),并且易于测试。不仅于此,它还提供 超爽的开发体验,比如有一个时间旅行调试器可以编辑后实时预览。
Redux 除了和 React 一起用外,还支持其它界面库。 它体小精悍(只有2kB,包括依赖)。
redux使用场景
典型的Web应用程序通常由共享数据的多个UI组件组成。通常,多个组件的任务是负责展示同一对象的不同属性。这个对象表示可随时更改的状态。在多个组件之间保持状态的一致性会是一场噩梦,特别是如果有多个通道用于更新同一个对象。
举个例子:一个带有购物车的网站。在顶部,我们用一个UI组件显示购物车中的商品数量。我们还可以用另一个UI组件,显示购物车中商品的总价。如果用户点击添加到购物车按钮,则这两个组件应立即更新当前的数据。如果用户从购物车中删除商品、更改数目、使用优惠券或者更改送货地点,则相关的UI组件都应该更新出正确的信息。可以看到,随着功能范围的扩大,一个简单的购物车将会很难保持数据同步。
Redux框架,它可以帮助你以简单易用的方式构建复杂项目并进行维护。
redux工作机制
在Redux中,所有的数据(比如state)被保存在一个被称为store的容器中 → 在一个应用程序中只能有一个。store本质上是一个状态树,保存了所有对象的状态。任何UI组件都可以直接从store访问特定对象的状态。要通过本地或远程组件更改状态,需要分发一个action。分发在这里意味着将可执行信息发送到store。当一个store接收到一个action,它将把这个action代理给相关的reducer。reducer是一个纯函数,它可以查看之前的状态,执行一个action并且返回一个新的状态。
Redux三大核心
Redux的核心由三部分组成:Store, Action, Reducer。
Store : 是个对象,贯穿你整个应用的数据都应该存储在这里。
Action:是个对象,必须包含type这个属性,reducer将根据这个属性值来对store进行相应的处理。除此之外的属性,就是进行这个操作需要的数据。
Reducer: 是个函数。接受两个参数:要修改的数据(state) 和 action对象。根据action.type来决定采用的操作,对state进行修改,最后返回新的state。
store
我们通过redux提供的createStore这个方法来创建一个Store。它接受对store进行处理的reducer作为参数。
Store有三个方法:
getState:用来获取store里面存储的数据。
dispatch: store里的数据不能直接修改,只能通过触发action来进行修改,这个方法就是用来触发action。
subscibe:订阅store改变时,要进行的操作。比如在react中,当store改变时,我们需要调用render方法对视图进行更新
Reducer
我们可以将对store的操作,写在一个reducer中,比如:
可以看到这个reducer对store的visibilityFilter和todos的两部分数据进行了处理。随着应用的复杂,如果我们把对所有数据的处理,都写在一个reducer中,那么它会变得很冗杂。如果我们将对每一部分的数据的处理,写在一个单独的reducer中,它接受该部分的数据作为state。那么整个reducer会变得整洁和清晰。
因此,redux为我们提供了combineReducer这个API,帮助我们分开书写reducer, 并且最终把这些reducer给集合到一个根reducer中。
react-redux
如果我们需要在react当中运用它,那么我们需要手动订阅store的状态变化,来对我们的react组件进行更新。那么react-reudx这个工具,就帮我们实现了这个功能,我们只需对store进行处理,react组件就会有相应的变化。
所以当我们在react项目当中应用redux时需安装:
npm install --save redux
npm install --save react-redux
两者关系图为如下
这个工具主要提供两个API:
connect
现在我们有了store,那么我们怎么才能在我们的组件中对它们进行操作呢?connect就为提供了这个功能。它接受mapStateToProps, mapDispatchToProps等作为参数。比如在我的TodoList这个组件中需要用到todos这部分数据,那么我完善mapStateToProps这个函数,它接受store中的state作为参数,返回一个对象,属性就是state中我们需要的数据:
mapStateToProps就将我们的state转换为了props对象。
同样的,我们可能需要在组件中对state进行处理。mapDispatchToProps就是帮助我们在组件中通过props调用dispatch来触发action的:
最后我们调用connect这个方法,将mapStateToProps, mapDispatchToProps生成的props注入到需要使用它的组中:
这样,我们在TodoList这个组件中,就能直接通过props.todos获取到todos中的数据, 通过props.onTodoClick对todos进行处理。
provider
上面我们调用connect时,在mapStateToProps 和 mapDispatchToProps我们分别用到了store的state和dispatch。但是在组件中的store是哪里凭空冒出来的呢?
provider就是来解决这个事的。Provider使它的子孙在调用connect方法时,都能获取到store。
这样,Provider的子孙组件都能在调用connect时获取到store。
总结:
Redux: store, action, reducer
store: getState, dispatch, subscribe
combineReducers
createStore
store ➡️ dispatch ➡️ action ⬅️ reducer
react-redux:
connect: 将store作为props注入
Provider: 使store在子孙组件的connect中能够获取到。