二、 redux模块化
对于大型项目来说,单文件不利于协作开发,代码也比较混乱难以维护,于是我们想办法将redux进行模块化拆分
拆分的思想应该是将reducer、action进行分类,将他们放在各自文件夹中
combineReducers合并子reducer
在进行项目的功能划分后,通常会针对每一模块创建自己的redux模块,这个模块具有自己独立的reducer、action、与切片state,用于管理自己的模块并将这个状态存储在全局中
子reducer最终要通过combineReducers合并成成一个具有自己key映射的reducer,在被setStore创建时,会形成自己独立的key映射的子state来进行模块化区分
不管如何最终的只会有一个store来维护状态,模块化状态只是做了key的映射,但还是存储在了store中
reducer拆分
文件目录 ./m1/reducer.js
const defaultState = { //创建切片state,它用于定义reducer的状态存储
goodsList:[]
}
const reducer = (preState = defaultState,action) => { //创建子reducer,使用默认state
switch (action.type) { //根据action的type,来进行相应的state设置
case "add":
return {
goodsList:preState.goodsList.concat([{name:"新信息",msg:action.msg}])
}
default:
return preState
}
}
module.exports=reducer //导出这个模块
action拆分
文件目录 ./m1/actionCreate.js
将针对某一模块的action对象与reducer放在一个文件夹,方便维护
const createGoods = (msg) => { //通过一个函数来进行传参,在dispatch时要传入一个函数调用
return {
type:"add",
msg
}
}
exports.createGoods=createGoods; //按需导出方式,方便添加新的action
进行模块汇总
文件目录 ./m1/index.js
const reducer = require("./reducer"); //导入子reducer
const action = require("./actionCreate"); //导入相应的处理方式
module.exports = {
action,
reducer
}
进行子reducer的合并
文件目录 ./reducerAll.js
模块化的核心就在此处,combineReducers能够将多个子reducer汇总成一个函数,这个函数再被setStore传入来构建store时,会按照他汇总的子reducer的key来创建切片store
const {reducer : m1} = require("./modules/m1"); //将模块reducer导入并起别名,进行区分
const {reducer : m2} = require("./modules/m2");
const {combineReducers} = require("redux");
const reducer = combineReducers({ //combineReducers会将多个子reducer合并为一个
m1, //这里的key决定了,在进行store创建时的切片store名
m2
});
module.exports = reducer
进行store的创建并引入合并好的总reducer
文件目录 ./store.js
const {createStore} = require("redux");
const reducer = require("./reducer"); //引入总reducer
const {createGoods} = require("./modules/m1/actionCreate"); //提取相应模块的处理action对象
const {createIncre,createDecre} = require("./modules/m2/actionCreate");
const store = createStore(reducer); //创建store
store.dispatch(createGoods("这是一条新消息")); //抛发一个action
store.dispatch(createIncre()) //抛发一个action
const unSubscribe = store.subscribe(() => {
console.log(JSON.stringify(store.getState())) //查看更改后的状态
});
最终的打印
{"m1":{"goodsList":[{"name":"新信息","msg":"这是一条新消息"}]},"m2":{"count":0}} //在初始化时会触发一次diapatch
{"m1":{"goodsList":[{"name":"新信息","msg":"这是一条新消息"}]},"m2":{"count":1}}
我们发现store的结构被进行了区分,每个模块存储在了自己相应的key里,而这个key正是我们使用combineReducers合并子reducer时进行定义的
命名空间问题
由于redux并没有采用命名空间这种方式来区分模块,模块在进行diapatch时是对根store抛发的,所以他会触发所有的子reducer,因此各个模块之间要明确好type的格式