1. 使用 combineReducers 拆分reducer
1. 第一步 安装 redux-devtools-extension
先在谷歌 网上应用商店安装 redux-devtools 扩展插件(访问不了的,可以自己翻墙,或者先装一个 谷歌访问助手 的扩展程序,然后就可以访问了)
然后 在github 上搜索 redux-devtools-extension
里面有 基本配置 和 高级配置(可以配置中间件),
按上面的方法, 配置在store/index.js 文件里面就行了, 然后就可以开发环境中查看数据状态信息了
2. 引入 combineReducers
文件拆分后的 格式
主文件 store/reducer.js ,导入子文件的reducer,整合一起导出
import {combineReducers} from 'redux'; // 目的, 避免文件过大, 拆分整合reducer
import {reducer as headerReducer} from '../common/header/store'; // 导入子文件reducer重命名
const reducer = combineReducers({ // 整合所有小的reducer
header:headerReducer
})
export default reducer;
子文件的reducer.js 还是固定写法,直接导出一个函数
const defaultState={
focused: false
}
export default (state=defaultState, action) =>{
if(action.type==='handle_focus'){
return{focused:true}
}
if(action.type==='handle_blur'){
return{focused:false}
}
return state;
}
子文件的index.js , 这样写, 导入的时候可以在后面少写一个 /reducer.js, 因为index.js 文件会自动执行嘛
最好出口文件都通过index.js导出出去
import reducer from './reducer';
export {reducer};
2. 使用 actionCreators 拆分 actions
1. 完整的文件目录
2. 先创建两个文件 actionCreators(action行为函数) 和 actionTypes (dispatch常量类型的名称);
actionTypes.js (定义常量, 如果常量报错,很快能找到)
// 这个文件就是定义常量来统一管理actionTypes
export const SEARCH_FOCUS = 'header/SEARCH_FOCUS'; // 前面的header是为了防止命名冲突, 类似命名空间的意思
export const SEARCH_BLUR = 'header/SEARCH_BLUR';
actionCreators (导出action函数)
import * as actionTypes from './actionTypes'; // 引入常量
export const handleFocus = ()=> ({
type: actionTypes.SEARCH_FOCUS,
})
export const handleBlur = ()=> ({
type: actionTypes.SEARCH_BLUR,
})
子文件下的 store/index.js (统一作出口文件,导出store里面的reducer , actionCreators , actionTypes)
import reducer from './reducer';
import * as actionCreators from './actionCreators';
import * as actionTypes from './actionTypes';
export {reducer , actionCreators , actionTypes};
组件中使用
import {actionCreators} from './store';
const mapAction = (dispatch) => {
return {
handleFocus() {
dispatch(actionCreators.handleFocus()) // 直接使用
},
handleBlur() {
dispatch(actionCreators.handleBlur())
}
}
}
3. 使用 imutable管理state
1. 首先, 我们要保证 state 不被修改, 需要自己手动处理复制一个新的对象, 这样处理存在风险
很可能自己不小心就改变了state
那么我们可以引入facebook提供 immutable库
yarn add immutable 安装依赖
然后 在 reducer 中引入 使用如下:
import {actionTypes} from './index';
import {fromJS} from 'immutable';
const defaultState=fromJS({ // immutable对象
focused: false
});
// 我们要保证 state 不被修改, 需要自己手动处理复制一个新的对象, 这样处理存在风险
// 很可能自己不小心就改变了state
// 那么我们可以引入facebook提供 immutable库
export default (state=defaultState, action) =>{
if(action.type===actionTypes.SEARCH_FOCUS){
return state.set('focused',true);
// immutable对象的set方法, 会结合之前的immutable对象的值
// 和设置的值, 返回一个全新的对象
}
if(action.type===actionTypes.SEARCH_BLUR){
return state.set('focused',false);
}
return state;
}
- 用 fromJS() 方法 , 把对象变成imutable对象
- 组件内 使用 get()方法,获取数据 例 focused: state.header.get('focused')
- reducer.js 使用 set 方法 设置新的值 例 state.set('focused',true);
4. 使用 redux-imutable 统一数据格式
1. 在组件内
const mapState = (state) => {
return {
focused: state.header.get('focused')
}
}
这句代码是存在问题的, state.是js对象调用, header后面是用immuteble对象get()方法, 应该统一成, 都用get()调用
那么在主reducer文件中,引入 combineReducers
之前是从redux中引入的, 现在改成redux-immutable
现在通过combineReducers()方法创造出的reducer就是immutable 对象了
// import {combineReducers} from 'redux';
import {combineReducers} from 'redux-immutable'; // 目的, 避免文件过大, 拆分整合reducer
import {reducer as headerReducer} from '../common/header/store'; // 导入重命名
const reducer = combineReducers({ // 整合所有小的reducer
header:headerReducer
})
export default reducer;
那么组件中获取数据时应该这样获取
const mapState = (state) => {
return {
// focused: state.get('header').get('focused')
focused: state.getIn(['header','focused']) // 两种写法都可以, 推荐这种写法
// getIn()方法里面传一个数组, 意思是head 下面的 focused
}
}