有关于React+redux的项目架构一直存在多种声音,目前主流的主要有三种:按照类型,按照页面功能,Ducks。

一,按照类型

   
 这里的类型指的是文件在项目中充当的角色类型,比如这个文件是一个component(展示组件),container(容器组件),在redux状态管理当中有,action,reducer等,这些不同角色的文件都放在一个单独的文件夹里,这种样式的结构也是react官方所推荐的结构。这种结构如下
    
使用这种结构组织项目,每当增加一个新功能的时候,需要再containers,components文件夹下增加这个功能需要的组件,还需要再actions,reducers文件夹下分别添加Redux管理这个功能使用到的action,reducer,此时如果actionType放在另外一个文件夹,还需要在这个文件夹下增加新的actionType,所以开发一个新的功能,需要再这些文件夹下频繁的切换已修改不同的文件。如果项目比较小,问题不大,如果对于一个规模比较大的项目使用这种项目结构非常的麻烦。
二,按照页面功能

   
既一个页面功能对应一个文件夹,这个页面功能所用到的container,component,action,reducer等文件都放在这个文件夹下。如下为按照页面功能划分的项目结构示列

  





这种结构好处很明显,一个页面功能使用到的组件,状态和行为都在同一个文件夹下,方便开发和维护,同时易于扩展,github上很多的脚手架也选择了这种目录结构,不足之处是依然同按角色划分面临同样的问题,改变一个功能需要频繁的在reducer,action,actionType等不同文件夹间切换。另外redux将整个的应用状态放在一个store中来管理,不同功能模块之间可以共享store中的部分状态(项目越复杂,这种场景会越多),共享的状态应该放到哪一个页面文件夹下也是一个问题,这些问题归根结底是因为redux中状态管理逻辑并不是根据页面功能划分的,它是页面功能之上的一种抽象。

  3,Ducks

     ducks指的是一种新的redux项目目录结构,,它提倡将相关的reducer,action,actionType和action
creaters写在一个文件里面,本质上是以应用状态作为划分模块的依据,而不是以页面的功能作为划分模块的依据,这样,管理相同状态的依赖都在同一个文件中,无论哪个容器组件需要这部分状态,只需要引入管理这个状态的模块文件即可,这样的一个文件(模块)代码如下:

    //module actions


const LOAD='widget/LOAD';const CREATE='widget/CREATE';const UPDATE=
'widget/UPDATE';const REMOVE='widget/REMOVE';
const initialState={ widget:null, isLoading:false}
//Reducer
export default function reducers(state=initialState,action={}){ switch (action.
stype){ LOAD: //... CREATE: //.... UPDATE: //.... REMOVE: //... default: return
state; }}
//Action Creators export function loadWidget(){ return {type:LOAD}; } export
function createWidget(widget){ return {type:CREATE,widget};}export function
updateWidget(widget){ return {type:UPDATE,widget};}export function removeWidget(
widget){ return {type:REMOVE,widget};}
整体的目录结构如下:




在前两种结构中,当container需要使用actions时,可以通过import * as actions from
'path/to/actions.js'的方式一次性的把一个action的文件中中所有的action
creates都引入进来。但在使用Ducks结构时,action
creater和reducer定义在同一个文件中,import*的导入方式会把reducer也导入进来(如果action types也被export
,那么还会导入action type)。为了解决这个问题。我们可以把action creators和action types定义到一个命名空间中:

 //widget.js


//Actions定义到types命名空间下export const types={ LOAD:'widget/LOAD', CREATE:
'widget/CREATE', UPDATE:'widget/UPDATE', REMOVE:'widget/REMOVE'}
const initialState={ widget:null, isLoading:false}
//Reducer
export default function reducers(state=initialState,action={}){ switch (action.
stype){ types.LOAD: //... types.CREATE: //.... types.UPDATE: //.... types.REMOVE
: //... default: return state; }}
//Action Creatorsexport const actions={ loadWidget:function(){ return {type:
types.LOAD}; }, createWidget:function(widget){ return {type:types.CREATE,widget
}; }, updateWidget:function(widget){ return {types:type.UPDATE,widget}; },
removeWidget:function(widget){ return {type:types.REMOVE,widget}; }
}

这样在container里面使用它的时候就可以通过import {actions} from
'path/to/modeuls.js'引入需要的对象,避免了不必要的引入,也避免了逐个引入action creaters的繁琐

注:首先感谢你对本文的阅读,不当之处欢迎拍正......

友情链接
KaDraw流程图
API参考文档
OK工具箱
云服务器优惠
阿里云优惠券
腾讯云优惠券
华为云优惠券
站点信息
问题反馈
邮箱:[email protected]
QQ群:637538335
关注微信