Store
import { createStore } from ‘redux‘;
const store = createStore(reducer);
在View中调用dispatch发送action
store.dispatch({ type: ‘ADD_TODO‘, payload: ‘Learn Redux‘ }); // 使用Action Creator store.dispatch(addTodo(‘Learn Redux‘));
reducer
创建Store的时候,需要传入一个函数作为Store的Reducer。以上dispatch之后,这个Action就会被传入到这个Store中的reducer进行处理,返回一个新的state
const reducer = function (state, action) { // ... return new_state; };
对于程序的初始状态,可以这么进行设置:
const reducer = (state = defaultState, action) => { switch (action.type) { case ‘ADD‘: return state + action.payload; default: return state; } };
规范要求Reducer是一个纯函数,所以必须要返回一个新的对象,手段如下:
function reducer(state, action) { return Object.assign({}, state, { thingToChange }); return { ...state, ...newState }; return [...state, newItem]; }
以上reduce返回了一个不同的对象(state),就代表界面需要刷新,因为状态发生变化了。这需要在view中对store进行监听:
store.subscribe(listener);
在以上的listener中调用setState即可。
回顾以上的逻辑(调用了Store的subscribe、getState和dispatch方法):
在模块中创建store,view引入这个模块,进行store.subscrible注册监听。
在注册的回调函数中,先调用store.getState获取到最新的状态,然后把数据通过setState更新到界面上(View模板中通过this.state.xx获取数据)
用于与view发生交互,view调用store.dispatch,然后store中的reducer被执行,返回一个新的state,以上的监听就会被触发
Reducer拆分
以上可以发现一个store中对状态的修改全部集中在reduce函数中,有必要对这个函数进行拆分
const chatReducer = (state = defaultState, action = {}) => { return { chatLog: chatLog(state.chatLog, action), statusMessage: statusMessage(state.statusMessage, action), userName: userName(state.userName, action) } };
可见以上的state中有3个字段,每个字段的值都通过一个函数的返回值来决定,在这个函数中进行action.type的判断,再进行数据修改,返回最新的值。
这个过程可以使用Redux提供的语法糖combineReducers进行更改(这里使用了对象的简洁写法):
const chatReducer = combineReducers({
chatLog,
statusMessage,
userName
})
State
一个view和一个state相互对应
const state = store.getState();
Action
用户与View发生交互,View发出Action,触发State的变化(因为State是从Store中获取的,所以也可以说成Store发生变化)
const action = { type: ‘ADD_TODO‘, payload: ‘Learn Redux‘ };
Action Creator简化Action的生成
function addTodo(text) { return { type: ADD_TODO, text } } const action = addTodo(‘Learn Redux‘);