exportinterfaceInitConfig<Mextendsobject =Models>{name?: string;models?: M;plugins?: Plugin[];redux?: InitConfigRedux;}// incrementer used to provide a store name if none exists
letcount=0;/**
* init
*
* generates a Rematch store
* with a set configuration
* @param config
*/exportconstinit=(initConfig: R.InitConfig={}):R.RematchStore=>{constname=initConfig.name||count.toString();count+=1;constconfig: R.Config=mergeConfig({...initConfig,name});returnnewRematch(config).init();};
exportdefaultclassRematch{// ...
protectedconfig: R.Config;protectedmodels: R.Model[];// ...
publicgetModels(models: R.Models):R.Model[]{returnObject.keys(models).map((name: string)=>({name,...models[name],reducers: models[name].reducers||{},}));}publicaddModel(model: R.Model){// ... some validation
// run plugin model subscriptions
this.forEachPlugin("onModel",(onModel)=>onModel(model));}publicinit() {// collect all models
this.models=this.getModels(this.config.models);for(constmodelofthis.models){this.addModel(model);}// create a redux store with initialState
// merge in additional extra reducers
constredux=createRedux.call(this,{redux: this.config.redux,models: this.models,});constrematchStore={name: this.config.name,...redux.store,// dynamic loading of models with `replaceReducer`
model:(model: R.Model)=>{this.addModel(model);redux.mergeReducers(redux.createModelReducer(model));redux.store.replaceReducer(redux.createRootReducer(this.config.redux.rootReducers));redux.store.dispatch({type:"@@redux/REPLACE "});},};this.forEachPlugin("onStoreCreated",(onStoreCreated)=>{constreturned=onStoreCreated(rematchStore);// if onStoreCreated returns an object value
// merge its returned value onto the store
if(returned){Object.keys(returned||{}).forEach((key)=>{rematchStore[key]=returned[key];});}});returnrematchStore;}}
/**
* isListener
*
* determines if an action is a listener on another model
*/constisListener=(reducer: string):boolean=>reducer.indexOf("/")>-1;exportdefaultfunction({redux,models,}:{redux: R.ConfigRedux;models: R.Model[];}){constcombineReducers=redux.combineReducers||Redux.combineReducers;constcreateStore: Redux.StoreCreator=redux.createStore||Redux.createStore;constinitialState: any=typeofredux.initialState!=="undefined"?redux.initialState:{};this.reducers=redux.reducers;this.createModelReducer=(model: R.Model)=>{constmodelBaseReducer=model.baseReducer;constmodelReducers={};for(constmodelReducerofObject.keys(model.reducers||{})){constaction=isListener(modelReducer)?modelReducer:`${model.name}/${modelReducer}`;modelReducers[action]=model.reducers[modelReducer];}constcombinedReducer=(state: any=model.state,action: R.Action)=>{// handle effects
if(typeofmodelReducers[action.type]==="function"){returnmodelReducers[action.type](state,action.payload,action.meta);}returnstate;};this.reducers[model.name]=!modelBaseReducer?combinedReducer:(state: any,action: R.Action)=>combinedReducer(modelBaseReducer(state,action),action);};// initialize model reducers
for(constmodelofmodels){this.createModelReducer(model);}// ...
}
constcomposeEnhancersWithDevtools=(devtoolOptions: R.DevtoolOptions={}):any=>{const{disabled,...options}=devtoolOptions;/* istanbul ignore next */return!disabled&&typeofwindow==="object"&&window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__?window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__(options):Redux.compose;};exportdefaultfunction({redux,models,}:{redux: R.ConfigRedux;models: R.Model[];}){// ...
constrootReducer=this.createRootReducer(redux.rootReducers);constmiddlewares=Redux.applyMiddleware(...redux.middlewares);constenhancers=composeEnhancersWithDevtools(redux.devtoolOptions)(...redux.enhancers,middlewares);this.store=createStore(rootReducer,initialState,enhancers);returnthis;}
exportdefaultclassRematch{// ...
publicinit() {// ...
// create a redux store with initialState
// merge in additional extra reducers
constredux=createRedux.call(this,{redux: this.config.redux,models: this.models,});constrematchStore={name: this.config.name,...redux.store,// dynamic loading of models with `replaceReducer`
model:(model: R.Model)=>{this.addModel(model);redux.mergeReducers(redux.createModelReducer(model));redux.store.replaceReducer(redux.createRootReducer(this.config.redux.rootReducers));redux.store.dispatch({type:"@@redux/REPLACE "});},};// ...
returnrematchStore;}}
可以看到,rematch store 在 redux store 的基础之上,增加了一个 name 属性和 model 方法,前者我猜测用于多个 rematch store 时的区分,而后者用于动态增加 model。主要看一下如何动态增加 model: