Redux是一个程序架构,源于Flux(Facebook提出的一种架构),然而,它不只能够应用于React,还能够应用于其余任何框架中。值得一提的是,Redux的源代码不多,可是他的逻辑拆分和函数式编程的设计思想是很是值得学习的。javascript
当一个JavaScript单页应用变得愈来愈复杂时,咱们要处理的数据(model)也变得愈来愈庞大,随之而来的是每一个数据的状态(state)会变得难以维护。当一个model改变时,咱们可能要手动处理由此引起的其余model的变化,更糟糕的是,其余model变化可能又会引发另外一些model的变化,这样产生连锁反应。最后咱们很容易就会不记得model在何时以及如何发生改变。这正是Redux能够解决的最大痛点之一—以统一的方式管理数据状态。html
统一的数据状态管理体现为如下2个方面:java
Action 是把数据从应用传到 store 的有效载荷。它是 store 数据的惟一来源。直白的说,action就是一种消息类型,他告诉Redux是时候该作什么了,并带着相应的数据传到Redux内部(即接下来介绍的Reducer)。
Action就是一个简单的对象,其中必需要有一个type属性,用来标志动做类型(reducer以此判断要执行的逻辑),其余属性用户能够自定义,但要尽可能简单。如:
{type: SET_ALL,index: 5}
react
Action Creator是一个用来自动生成Action的函数,这也是Redux函数式编程的一种体现。一般,咱们会按照业务逻辑或组件把相关的Action Creator放在一个文件中,形式以下:编程
export const SHOW_SLIDER = 'SHOW_SLIDER';
export const RIGHT_SLIDER = 'RIGHT_SLIDER';
export const showSliderAction = (index) => {
return {
type: SHOW_SLIDER,
index
};
}
export const rightSliderAction = (length) => {
return {
type: RIGHT_SLIDER,
length
};
}
复制代码
其中showSliderAction和rightSliderAction就是Action Creator。
因为Action Creator的形式大致相同,咱们还能够建立一个用来生成Action Creator的函数以进一步简化。redux
export const makeCreateAction = (type, ...keys) => {
return (...data) => {
let action = {type};
keys.forEach((v,i) => action[v] = data[i]);
return action;
}
}
export const showSliderAction = makeCreateAction(SHOW_SLIDER, index);
export const rightSliderAction = makeCreateAction(RIGHT_SLIDER, length);
复制代码
Reducer 指定了应用状态的变化如何响应 actions 并发送到 store 的,action只是告诉Redux该干什么了,并无告诉他怎么干,而reducer就是根据action处理state如何改变的逻辑。
Reducer必须是一个纯函数(缘由稍后解释),他根据action处理state的更新,若是没有更新或遇到未知action,则返回旧state;不然返回一个新state对象。注意:不能修改旧state,必须先拷贝一份state,再进行修改,也可使用Object.assign函数生成新的state。另外,state参数需先进行初始化。实例代码以下:bash
//初始状态
let initialState = {hiddenClass: 'g-hidden',currentIndex:0};
let sliderReducer = function (state = initialState, action) {
switch(action.type){
case sliderAction.SHOW_SLIDER:
return {hiddenClass: '',currentIndex:action.index};
case sliderAction.RIGHT_SLIDER:
if(state.currentIndex == action.length-1){
return Object.assign({}, state, {currentIndex:0});
}else{
return Object.assign({}, state, {currentIndex:Number.parseInt(state.currentIndex)+1});
}
default:
return state;
}
}
export default sliderReducer;
复制代码
使用纯函数的缘由:
首先,纯函数的特色是:架构
若是不使用纯函数,即直接更改state值会怎么样呢?并发
… …
case sliderAction.RIGHT_SLIDER:
if(state.currentIndex == action.length-1){
state.currentIndex = 0;
return state;
}
… …
复制代码
以后会发现,不管state如何变化,UI都不会更新。如下是Redux的部分源码:框架
import { combineReducers } from 'redux';
import photomainReducer from './photomainReducer';
import sortReducer from './sortReducer';
import sliderReducer from './photoSliderReducer';
export default combineReducers({
photomainReducer,
sortReducer,
sliderReducer
});
复制代码
1.维持应用的 state;
2.提供 getState() 方法获取 state;
3.提供 dispatch(action) 方法更新 state;
4.经过 subscribe(listener) 注册监听器;
5.经过 subscribe(listener) 返回的函数注销监听器。
const store = createStore(
indexPhotomainReducer,
);
export default store;
复制代码
// 每次 state 更新时,打印日志
// 注意 subscribe() 返回一个函数用来注销监听器
const unsubscribe = store.subscribe(() =>
console.log(store.getState())
)
// 中止监听 state 更新
unsubscribe();
复制代码
store.dispatch(SHOW_SLIDER)
复制代码
let initialState = {hiddenClass: 'g-hidden',currentIndex:0};
let sliderReducer = function (state = initialState, action) {
switch(action.type){
case sliderAction.SHOW_SLIDER:
return {hiddenClass: '',currentIndex:action.index};
default:
return state;
}
}
复制代码
store.subscribe(listener);
复制代码
function listerner() {
let newState = store.getState();
component.setState(newState);
}
复制代码
以上为Redux的数据流动过程。
本篇到此告一段落,下一篇介绍Redux的异步实现。