Redux 简要的说就是一个事件分发器和全局
state
控制台。
Redux 有一个全局的state
,通过将根组件包进Provider
,将store
分发给所有的子组件,而子组件通过connect
方法,获取dispatch
事件分发函数,以及需要的props
(如果有需要也可以通过connect
传入想分发给子组件的action
)
定义常量、state和Action
// Reducer/ConstValue.js export const ADD_NEW = 'add_new'; export const INCREASE = 'increase'; export const DECREASE = 'decrease'; export const DELETE = 'delete'; export INITIAL_STATE = { objList: [ { number: 0 } ] }; // Reducer/ActionCreator.js import { ADD_NEW,DELETE INCREASE,DECREASE } from './ConstValue'; export function addNew(obj) { return { type: ADD_NEW,obj } } export function delete(index) { return { type: DELETE,index } } export function increase(number,index) { return { type: INCREASE,number,index } } export function decrease(number,index) { return { type: DECREASE,index } }
定义Reducer
Reducer 会注册给 store,用于处理 action 事件
// Reducer/Reducers.js import { ADD_NEW,DECREASE,INITIAL_STATE } from './ConstValue'; let objList = INITIAL_STATE.objList; export function objList(state=objList,action) { switch (action.type) { case ADD_NEW: return [...state,action.obj]; case DELETE: return [...state.slice(0,action.index),...state.slice(action.index + 1) ]; case INCREASE: case DECREASE: return [...state.slice(0,Object.assign({},state[action.index],{number: number(state[action.index].number,action)}),...state.slice(action.index + 1) ]; default: return state; } } export function number(state=objList[0].number,action) { switch (action.type) { case INCREASE: return state + action.number; case DECREASE: return state - action.number; default: return state; } }
IMPORTANT
Reducer 传入(state,action),通过判断action
的type
,进行事件分发处理。当事件很多的时候可以把 Reducer 拆分,最后通过combineReducers
进行组合。
每个 Reducer 都要有明确的返回值,当siwtch
到default
的时候则返回传入的state
本身。在处理state
的时候,不要在原有参数上修改,而应该返回一个新的参数,例如
return Object.assign({},state[0],{number: action.number}); // 通过Object.assign获取一份state[0]的拷贝,并修改state[0]中的number数据 return [...state,action.obj]; // 通过[...XXX]得到一个新的数组,并在最后加入action.obj
combineReducers
// Reducer/index.js import { combineReducers } from 'redux'; import * as appReducers from './Reducers'; export const AppReducer = combineReducers(appReducers);
上述代码中,通过import * as appReducers
导出全部的 Reducer,之后利用combineReducers
黑魔法快速的组合 Reducer
黑魔法发动条件
每个 Reducer 的名称,必须与它获取的 state 参数名称一样,例如:
export function objList(state=objList,action){} export function number(state=objList[0].number,action){}
如果你任性的不想那么写,那么就要:
// Reducer/Reducers.js export function reducerA(state=objList,action){} export function reducerB(state=objList[0].number,action){} // Reducer/index.js import { combineReducers } from 'redux'; import { reducerA reducerB,} from './Reducers'; export function AppReducer(state,action) { return { objList: reducerA(state.objList,number: reducerB(state.objList[0].number,action) } }
注入到React
// 安装React绑定库 sudo npm install --save react-redux
在根组件上,通过Provider
注入store
只有一个Store
// App/index.js import { Provider } from 'react-redux'; import { createStore } from 'redux'; import { AppReducer } from '../Reducer/index'; import RootComponent from './RootComponent'; let appStore = createStore(AppReducer); render( <Provider store={appStore}> <RootComponent /> </Provider>,document.getElementById('index_body') ); // App/RootComponent.js import ContentComponent from './ContentComponent'; class RootComponent extends Component { render() { return ( <div> <ContentComponent /> <div> ) } } export default ContentComponent;
注入store
后,根组件所有的组件都可以获取到dispatch
函数,以便进行action
的分发处理
子组价获取props和dispatch
// App/ContentComponent.js import { increase,decrease } from '../Reducer/ActionCreator'; class ContentComponent extends Component { render() { const {obj,increaseNumber,decreaseNumber} return ( <div> <span onClick={() => { increaseNumber(1); }}>加一</span> <span>{obj.number}</span> <span onClick={() => { decreaseNumber(1); }}>减一</span> </div> ) } } // 定义props筛选函数,以state作为传入参数,选出需要注入该组件作为props的state. 不是必须,不写则state作为props全部注入 const mapStateToProps = (state) => { return { obj: state.objList[0] // objList: state.objList // 本来想写list增删逻辑的但是太懒了暂时搁浅.. } } // 定义action筛选函数,以dispatch作为传入参数,选出需要注入该组件需要使用的action. 不是必须 const mapDispatchToProps = (dispatch) => { return { increaseNumber: (number) => { dispatch(increase(number)); },decreaseNumber: (number) => { dispatch(decrease(number)); } } } import { connect } from 'react-redux'; export default connect(mapStateToProps,mapDispatchToProps)(ContentComponent); // 不使用筛选函数的时候: // export default connect(mapStateToProps)(ContentComponent); // export default connect()(ContentComponent);
在通过connect
进行注入的时候,dispatch
已经作为组件的 props 而存在了。所以当需要传入的事件很多,感觉写mapDispatchToProps
很繁琐的时候,还有另外一种写法:
// App/ContentComponent.js import { increase,dispatch} return ( <div> <span onClick={() => { dispatch(increaseNumber(1)); }}>加一</span> <span>{obj.number}</span> <span onClick={() => { dispatch(decreaseNumber(1)); }}>减一</span> </div> ) } } import { connect } from 'react-redux'; export default connect(mapStateToProps)(ContentComponent);
优劣势
优势
通过 Redux,我们可以少些很多繁琐的事件传输。在 Redux 之前,顶层组件处理 state 的改变,而触发的事件则有可能需要层层传递给底层的子组件,子组件触发之后再次层层回调传到顶层。
但 Redux 的 state 是全局的,不必关心哪个组件触发setState()
函数,只需要设定好action
和处理 action 的reducer
,由store
进行分发处理。
那样的话,我们可以在底层触发 state 的改变而不必担心向上调用 --- 触发的 action 改变将被 store 监听,dispatch 给 reducer,reducer通过判断action.type
,做出适当的反应处理 state
劣势
action 很多很繁琐
一开始的架构很重要,否则后期改动不易
淡化了传统React的组件传输事件与props的思想,可能一开始不易理解