cretaeStore
此函数是用来创建一个单应用存放所有state的store的函数。它接收三个参数。并且返回dispatch, subscribe, getSatte, replaceRecuder, observable。
参数
- reducer
- 接收两个参数(state,action),并且返回新的state树。
- 通常会使用combineReducers将自己定义的reducers进行组合。并返回一个函数。
随着应用变得复杂,需要对reducer函数进行拆分, 拆分后的每一块独立负责管理state的一部分。
combineReducers辅助函数的作用是,把一个有多个不同的reducer函数作为value的object,合并成一个最终的reducer函数(返回的函数对旧的state和新的state做了浅比较!==, 如果浅比较不相等, 则返回新的state,否则就是旧的state,为的是性能优化)。然后把这个函数传递给createStore。下边源码的最下边
function combineReducers(reducers) { var reducerKeys = Object.keys(reducers); var finalReducers = {}; for (var i = 0; i < reducerKeys.length; i++) { var key = reducerKeys[i]; if (process.env.NODE_ENV !== 'production') { if (typeof reducers[key] === 'undefined') { warning("No reducer provided for key \"" + key + "\""); } } if (typeof reducers[key] === 'function') { finalReducers[key] = reducers[key]; } } var finalReducerKeys = Object.keys(finalReducers); // This is used to make sure we don't warn about the same // keys multiple times. var unexpectedKeyCache; if (process.env.NODE_ENV !== 'production') { unexpectedKeyCache = {}; } var shapeAssertionError; try { assertReducerShape(finalReducers); } catch (e) { shapeAssertionError = e; } return function combination(state, action) { if (state === void 0) { state = {}; } if (shapeAssertionError) { throw shapeAssertionError; } if (process.env.NODE_ENV !== 'production') { var warningMessage = getUnexpectedStateShapeWarningMessage(state, finalReducers, action, unexpectedKeyCache); if (warningMessage) { warning(warningMessage); } } var hasChanged = false; var nextState = {}; for (var _i = 0; _i < finalReducerKeys.length; _i++) { var _key = finalReducerKeys[_i]; var reducer = finalReducers[_key]; var previousStateForKey = state[_key]; var nextStateForKey = reducer(previousStateForKey, action); if (typeof nextStateForKey === 'undefined') { var errorMessage = getUndefinedStateErrorMessage(_key, action); throw new Error(errorMessage); } nextState[_key] = nextStateForKey; hasChanged = hasChanged || nextStateForKey !== previousStateForKey; } hasChanged = hasChanged || finalReducerKeys.length !== Object.keys(state).length; return hasChanged ? nextState : state; };}
当然也可以使用其它类似的函数来管理所有的reducers。
- preloadedState
state树的初始化数据。他和reducer参数中的es6的默认值。二选其一。
初始值的作用,是为了不让reducer返回state=undefiend,是为了避免错误扩散。
场景: 1.不使用combineReducers时,
1.1 只要使用preloadedState时, createStore都会取preloadedState当做初始值。假如在reducer中使用默认值, reducer的默认值优先级则小与preloadedState;
1.2.不使用preloadedState时, 使用reducer默认值,则会redcer的优先级高于preloadedState。
场景一。看例子1.
//例子1.不使用combineReducers的时候。使用preloadedState和不使用默认值的优先级。
let preloadedState= {OneReducer :{a:1}}
store = createStore(OneReducer, preloadedState)
store.subscribe(()=>{
console.log( "不使用combineReducers的时候。preloadedState和默认值的优先级", store.getState())
})
//reducer
//场景一,且使用preloadedState时export function OneReducer (state, action) { let newState = {} switch (action.type) { case 'one_type': { newState ={...state, ...action.params.data} } break; default:newState = state; } return newState || state}
会发现,当使用preloadedState且不使用es6的默认值时, 会自动取preloadedState放到state树上。
下边是createStore部分源码,只截取dispatch和preloadedState部分。
function createStore(reducer, preloadedState, enhancer) { var _ref2; if (typeof preloadedState === 'function' && typeof enhancer === 'undefined') { enhancer = preloadedState; preloadedState = undefined; } var currentReducer = reducer; var currentState = preloadedState; var currentListeners = []; var nextListeners = currentListeners; var isDispatching = false; function getState() { if (isDispatching) { throw new Error('You may not call store.getState() while the reducer is executing. ' + 'The reducer has already received the state as an argument. ' + 'Pass it down from the top reducer instead of reading it from the store.'); } return currentState; } function dispatch(action) { if (!isPlainObject(action)) { throw new Error('Actions must be plain objects. ' + 'Use custom middleware for async actions.'); } if (typeof action.type === 'undefined') { throw new Error('Actions may not have an undefined "type" property. ' + 'Have you misspelled a constant?'); } if (isDispatching) { throw new Error('Reducers may not dispatch actions.'); } try { isDispatching = true; currentState = currentReducer(currentState, action); } finally { isDispatching = false; } var listeners = currentListeners = nextListeners; for (var i = 0; i < listeners.length; i++) { var listener = listeners[i]; listener(); } return action; } dispatch({ type: ActionTypes.INIT }); return _ref2 = { dispatch: dispatch, subscribe: subscribe, getState: getState, replaceReducer: replaceReducer }, _ref2[$$observable] = observable, _ref2;}
在上边源码中,可看到createStore内部自调用了dispatch并且给定了默认的action、在dispatch函数中, 会调用每一个reducer函数。并且赋给reducer函数参数为currentState,action。因为是dispatch(redux默认的action)所以此时的currentState则是 preloadedState参数的值。所以reducers函数返回的state树,也就是preloadedState值。
由于在调用createStore时, 会默认初始化调用dispatch, 在dispatch中, 会循环调用每一个reducer。此时如果preloadedState和es6默认值都不存在的话, 会使state为undefined并且返回。如果返回了state=undefined,那在具体使用时,会因为找不到而报错。所以redux干脆就不让state=undefined。会加层校验。
场景二。看例子2.
//例子2.不使用combineReducers的时候。不使用preloadedState且使用默认值的优先级。
store = createStore(OneReducer)
store.subscribe(()=>{
console.log( "不使用combineReducers的时候。preloadedState和默认值的优先级", store.getState())
})
//reducer
//场景二,
let initdata = { OneReducer:{value:"哈哈哈哈,我是state的默认值"}}
export function OneReducer (state = initdata, action) {
let newState = {}
switch (action.type) {
case 'one_type': {
newState ={...state, ...action.params.data}
}
break;
default:newState = state;
}
return newState || state
}
当不使用preoloadedState时, 因为使用了es6的默认值功能。所以在初始dispatch时,调用reducer参数state=undefined,也不会报错。
场景三。使用combineReducers,使用preloadedState,且不使用es6默认值时。
//reducers
import {combineReducers} from "redux";import OneReducer from "./one.reducer.js";import TwoReducer from "./two.reducer.js";import ThreeReducer from "./three.reducer.js";export default combineReducers({ OneReducer, TwoReducer, ThreeReducer})
//store
let preloadedState={OneReducer :{OneReducer:1}} store = createStore(Reducers, preloadedState)//Reducers就是上边定义的类组件 store.subscribe(()=>{ console.log( "使用combineReducers的时候。preloadedState和默认值的优先级", store.getState()) })//onereducer
export function OneReducer (state , action) {
let newState = {}
switch (action.type) {
case 'one_type': {
newState ={...state, ...action.params.data}
}
break;
default:newState = state;
}
return newState || state
}//combineReducers中的一个调用方法,源码
function assertReducerShape(reducers) { Object.keys(reducers).forEach(function (key) { var reducer = reducers[key]; var initialState = reducer(undefined, {//这里显示的传递undefined type: ActionTypes.INIT }); if (typeof initialState === 'undefined') { throw new Error("Reducer \"" + key + "\" returned undefined during initialization. " + "If the state passed to the reducer is undefined, you must " + "explicitly return the initial state. The initial state may " + "not be undefined. If you don't want to set a value for this reducer, " + "you can use null instead of undefined."); } if (typeof reducer(undefined, { type: ActionTypes.PROBE_UNKNOWN_ACTION() }) === 'undefined') { throw new Error("Reducer \"" + key + "\" returned undefined when probed with a random type. " + ("Don't try to handle " + ActionTypes.INIT + " or other actions in \"redux/*\" ") + "namespace. They are considered private. Instead, you must return the " + "current state for any unknown actions, unless it is undefined, " + "in which case you must return the initial state, regardless of the " + "action type. The initial state may not be undefined, but can be null."); } });}
由于使用了combineReducers,所以会先调用combineReducers函数。preloadedState不会再此函数中出现。只能取默认值。在combineReducers中, 会默认调用一次每一个reducer,并且state赋值为undefined。此时在reducer中的默认值,就会起作用**。**
此时还没有使用默认值, 所以redux内部会报异常如下
场景四。使用combineReducers,使用preloadedState,且使用es6默认值时。
//store
let preloadedState={OneReducer :{one:1}} store = createStore(Reducers, preloadedState)//Reducers就是上边定义的类组件 store.subscribe(()=>{ console.log( "使用combineReducers的时候。preloadedState和默认值的优先级", store.getState()) })//onereducer
let initdata = { OneReducer:{value:"哈哈哈哈,我是state的默认值"}}export function OneReducer (state = initdata , action) {
let newState = {}
switch (action.type) {
case 'one_type': {
newState ={...state, ...action.params.data}
}
break;
default:newState = state;
}
return newState || state
}
会发现,其实默认值会采用preloadedState的。
其实无论那种场景, 只要使用的preloadedState,都会以这个值为主。
场景五。使用combineReducers,不使用preloadedState,且使用es6默认值时。
//store
store = createStore(Reducers)//Reducers就是上边定义的类组件
store.subscribe(()=>{
console.log( "使用combineReducers的时候。preloadedState和默认值的优先级", store.getState())
})
//onereducer
let initdata = { one:"哈哈哈哈,我是state的默认值"}export function OneReducer (state = initdata , action) {
let newState = {}
switch (action.type) {
case 'one_type': {
newState ={...state, ...action.params.data}
}
break;
default:newState = state;
}
return newState || state
}
- enhancer
它是一个组合store creator的高阶函数, 返回一个新的强化过的store 。
可以指定使用第三方插件,redux附带的唯一存储增强器是applyMiddleware
import {createStore, applyMiddleware} from "redux";
store = createStore(Reducers, preloadedState, applyMiddleware())
//enhancer参数的源码中使用如下
return enhancer(createStore)(reducer, preloadedState);其实就相当于
return applyMiddleware()(createStore)(reducer, preloadedState);
//applyMiddleware源码
function applyMiddleware() { for (var _len = arguments.length, middlewares = new Array(_len), _key = 0; _key < _len; _key++) { middlewares[_key] = arguments[_key]; } return function (createStore) { return function () { var store = createStore.apply(void 0, arguments); var _dispatch = function dispatch() { throw new Error("Dispatching while constructing your middleware is not allowed. " + "Other middleware would not be applied to this dispatch."); }; var middlewareAPI = { getState: store.getState, dispatch: function dispatch() { return _dispatch.apply(void 0, arguments); } }; var chain = middlewares.map(function (middleware) { return middleware(middlewareAPI); }); _dispatch = compose.apply(void 0, chain)(store.dispatch); return _objectSpread({}, store, { dispatch: _dispatch }); }; };}
上边源码中表示:applyMiddleware返回一个函数,返回的函数里,又返回了一个函数。运用的是函数式编程的柯理化编程(将多个参数的函数转换成接收一个参数的函数。)
return applyMiddleware()(createStore)(reducer, preloadedState);时,
首先会先调用applyMiddleware(),返回第一个接收createStore的函数。
applyMiddleware()(createStore),返回一个增强store的函数。
applyMiddleware()(createStore)(reducer, preloadedState),返回的就是增强后的store。
在最后的返回函数中, 我们可以看到,
1. 先是创建了store, 然后将声明了一个_dispatch函数。
2. 继续声明了middlewareAPI, 并附初始化值, store.getState, 和自定义的_dispatch函数。
3. 将传进来的中间件遍历附上middlewareAPI,返回数组。
4.将所有的中间件组合强化的dispatch赋值给_dispatch。
5.最终返回store。
学艺不精,请多多指教。