Redux是一个JavaScript状态容器,提供可预测的状态管理。
Redux是在Flux的基础上生产的。基本思路是保证数据单向流动,同时方便控制、使用和测试。Redux不依赖于其他JavaScript库。
随着JavaScript单页应用程序的开发变得越来越复杂,JavaScript需要管理的状态比以往任何时候都多。这些状态可以包括服务器响应、缓存的数据、本地生成的尚未保存到服务器的数据,以及用户界面状态,例如激活的路由、选择的标签、是否显示加载活动或寻呼机等。
跟随Flux、CQRS和Event Sourcing的脚步,Redux试图通过限制更新的时间和方式来使状态的变化可预测。这些限制体现在Redux的三个原则中:
单一数据源。整个应用状态存储在对象树中,并且该对象树只存在于唯一存储中。状态是只读的。改变状态的唯一方法是触发动作,动作是一个普通的对象,用来描述已经发生的事件。使用纯函数进行修改。要描述操作如何改变状态树,您需要编写reducers。
Redux主要分为三个部分:动作、减速器和存储。
行动.动作非常简单,它是一个包含{type,payload}的简单对象。类型是一个常数,用来表示动作的类型,有效载荷是这个动作携带的数据。需要通过store.dispatch()方法发送操作。减速器.Reducer用于处理由Action触发的状态树的更改。因此,一个reducer函数将接受两个参数,oldState和action,并返回一个新的状态:(oldstate,action)=newstate。商店.商店的功能是连接行动和减速器。Store的功能如下:保存整个应用程序的状态树;提供getState()方法获取状态;提供dispatch()方法来发送更改状态的操作;提供subscribe()方法注册回调函数来监控状态的变化,严格的单向数据流是Redux架构设计的核心。store . dispatch(action)-reducer(state,action)-store.getstate()构成了一个单向数据流。
Redux应用程序中数据的生命周期遵循以下四个步骤:
调用store.dispatch(操作)。reducxstore调用传入的reducer函数。根缩减器应该将多个子缩减器输出组合成一个状态树。reducxstore保存根reducer返回的完整状态树。
Flux是一个应用架构,或者说是一个想法。这与REAT本身无关。它可以在REAT或其他框架中使用。
Flux主要由Dispatcher、Store、View和Action四个部分组成,其中Dispatcher是Flux的核心中枢,相当于一个事件分发器,收集分散在各个组件中的逻辑代码,在Dispatcher中统一处理。
完整的Flux处理流程如下:用户与视图交互或从外部生成一个动作,Dispatcher接收该动作并执行注册的回调,以将该动作分发到所有Store。通过注册的回调,存储响应与它们的保存状态相关的操作。然后,商店将触发一个更改事件,提醒控制器视图数据已经更改。控制器视图监听这些事件
重新从 Store 中获取数据。这些 controller-views 调用他们自己的 setState() 方法,重新渲染自身以及组件树上的所有后代组件。Redux 的灵感来源于 Flux 的几个重要特性,它可以看作是 Flux 的一种实现。和 Flux 一样,Redux 规定,将模型的更新逻辑全部集中于一个特定的层,都不允许程序直接修改数据,而是用一个叫作 “action” 的普通对象来对更改进行描述。不同的是:
应用中所有的 state 都以一个对象树的形式储存在一个单一的 store 中。唯一改变 state 的办法是触发 action,一个描述发生什么的对象。为了描述 action 如何改变 state 树,需要编写 reducers。
// 这是一个 reducer,形式为 (state, action) => state 的纯函数。 function counter(state = 0, action) { switch (action.type) { case 'INCREMENT': return state + 1; case 'DECREMENT': return state - 1; default: return state; } } // 创建 Redux store 来存放应用的状态 let store = createStore(counter); // 可以手动订阅更新,也可以事件绑定到视图层。 store.subscribe(() => console.log(store.getState()) ); // 改变内部 state 唯一方法是 dispatch 一个 action。 store.dispatch({ type: 'INCREMENT' }); // 输出:1 store.dispatch({ type: 'INCREMENT' }); // 输出:2 store.dispatch({ type: 'DECREMENT' }); // 输出:1
以上代码,首先定义改变应用状态的对象,这个对象被叫做 action,而不是直接改变 state。然后编写专门的函数来决定每个 action 如何改变应用的 state,这个函数被叫做 reducer。
Redux只有一个单一的 store 和一个根级的 reduce 函数(reducer)。
随着应用越来越大,一方面,不能把所有的数据都放到一个reducer里面,另一方面,为每个reducer创建一个store,后续store的维护就显得比较麻烦。combineReducers 辅助函数的作用是,把一个由多个不同 reducer 函数作为 value 的 object,合并成一个最终的 reducer 函数,然后就可以对这个 reducer 调用 createStore。合并后的 reducer 可以调用各个子 reducer,并把它们的结果合并成一个 state 对象。state 对象的结构由传入的多个 reducer 的 key 决定。
// 创建两个reducer function todos(state = [], action) { switch (action.type) { case 'ADD_TODO': return state.concat([action.text]) default: return state } } function counter(state = 0, action) { switch (action.type) { case 'INCREMENT': return state + 1 case 'DECREMENT': return state - 1 default: return state } } // 将多个reducer合并成一个 var combineReducers = require('../../lib/redux/redux').combineReducers; var rootReducer = combineReducers({ todos, counter }); var createStore = require('../../lib/redux/redux').createStore; var store = createStore(rootReducer); console.log(store.getState()) // { // counter: 0, // todos: [] // } store.dispatch({ type: 'ADD_TODO', text: 'Use Redux' }); // { // counter: 0, // todos: [ 'Use Redux' ] // }