博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
React + Redux + react router技术栈架构
阅读量:7236 次
发布时间:2019-06-29

本文共 3640 字,大约阅读时间需要 12 分钟。

前些日子刚学习了React,觉得很不错,很符合我的逻辑。于是还没弄明白,就迫不及待的开始了一个中型项目(我觉得)(其实是项目需要赶紧开始,没时间了...咳咳)。期间不出所料地遇到了很多坑和问题,也得到了很多收获,特开几篇文章记录下来。

概述

本文是《使用React技术栈的一些收获》系列文章的第一篇,介绍了项目是如何架构的。

具体技术栈

项目技术栈使用的是React全家桶:React+redux+react router+es6+webpack+sass以及Data到View层我们使用了reselect。由于数据处理逻辑并不复杂,因此并没有使用immutable.jsRedux saga(后来我觉得连Redux都没必要用);样式方面考虑到可读性和开发人数较少(俩),我们并没有使用流行的CSS-module。

脚手架的选择

选择脚手架就选择了整体架构,我选择的是,也是最受欢迎的脚手架之一。并在它的基础上安装了一些用到的包,删去了一些不用的包,让它更适合我们的项目。

项目架构

项目目录如下:​

根据脚手架的架构,我们构建的是一个React单页应用。

总体来说

就是采用React router plain object+combineReducer+require.ensure的写法把不同的路由分割在routes目录下,对应不同的页面,做代码分割、按需加载。逻辑图如下:

具体来说

首先src目录下有一个main.js,它用来创建store,并拿到路由(plain object形式),然后注入到顶层的Provider组件和其下的Router组件:

src下的main.js文件:
const initialState = window.___INITIAL_STATE__const store = createStore(initialState)// 创建store​const MOUNT_NODE = document.getElementById('root')​let render = () => {  const routes = require('./routes/index').default(store)// 拿到路由​  ReactDOM.render(    
, //注入 MOUNT_NODE )}复制代码

reduxstore也随着页面分割而分割:​

不同页面下的modules下的文件只负责本页面所需的所有actionreducer,并通过加载页面injectreducer里,然后在src/store/reduce.js文件里combine,最后被引入到src/store/createStore里和同时引入的redux中间件一起创建store

src/store目录下的reducer.js:
export const makeRootReducer = (asyncReducers) => {  return combineReducers({    auth: auth,    form: formReducer,    location: locationReducer,    ...asyncReducers   // 各页面下的reducer注入到这里  })}​export const injectReducer = (store, { key, reducer }) => {  store.asyncReducers[key] = reducer  store.replaceReducer(makeRootReducer(store.asyncReducers))//注入时更新}复制代码
以及src/store下的createStore文件:
const store = createStore(    makeRootReducer(),    initialState,    compose(      applyMiddleware(...middleware),      ...enhancers    )  )复制代码

routes目录下有一个index.js文件,它使用plain object的写法集合各路由对应的页面;

routes下的index.js文件:(用来包含各页面)

src/routes/index.js:(采用React router plain object写法)

import CoreLayout from '../layouts/CoreLayout'import Home from './Home'import FollowRoute from './Follow'import SignRoute from './Sign'import HallRoute from './Hall'import UserPageRoute from './UserPage'import PageNotFound from './PageNotFound'import Redirect from './PageNotFound/redirect'​export const createRoutes = (store) => ({  path: '/',  component: CoreLayout,  indexRoute: Home,  childRoutes: [        // 各页面    FollowRoute(store),    SignRoute(store),    HallRoute(store),    UserPageRoute(store),    PageNotFound(),    Redirect  ]})复制代码

每个页面目录下也有一个index.js文件并使用getComponent + webpack ensure按需加载页面的containerreducer

每个页面下的index.js文件:(负责输出这个页面)

src/routes/sign/index.js(其他页面差不多,举个例子)

import { injectReducer } from '../../store/reducers'// 引入注入reducer函数​export default (store) => ({  path: 'sign', //页面路由  getComponent (nextState, cb) {    require.ensure([], (require) => {  // webpack按需加载      const Sign = require('./containers/SignContainer').default //引入总container      const reducer = require('./modules/index').default//引入总reducer      injectReducer(store, { key: 'sign', reducer })// 加载时注入页面reducer到主reducer      cb(null, Sign)// 返回页面    })  }})复制代码

在每个页面下,index.js是获得每个页面的入口,每个页面都有自己的componentscontainers以及actionsreducers,目录看起来像这样:

componentscontainers都是这个页面下的组件和容器,如果其他页面也会使用里面的组件和容器,就会把他们放在src/component和src/containers下共用。modules下的文件是这个页面所有的action和reducer。如果页面逻辑可以分离,会把各逻辑下的reducer抽离并单开一个index.js,并在其中combine:

=>

总结与反思

通过上述架构,项目代码逻辑变得很清晰,每一个文件都有其专属的功能,互不影响,开发过程变得工程化、流程化,思路很清晰,代码出错率大大降低,开发速度大大提高。React router plain object+redux combineReducer的组合很好的将代码按不同页面做了分割;而 getComponent + webpack ensure又做到了页面的按需加载,项目页面运行速度提升了不少。但是有一个问题,在react route4.0版本中getComponent被移除了,并提供了更加简洁的方式(实际上就是替你做了按需加载):Bundle组件+webpack 加载器undle-loader。使用这种方式的话,目录结构将会变得更简单、更容易理解,避免了多层嵌套,因此,项目还需要改善。

转载地址:http://dpgfm.baihongyu.com/

你可能感兴趣的文章
(十七)java冒泡排序和compareto
查看>>
linux内存查看方式
查看>>
Java魔法堂:String.format详解-
查看>>
线性重复动画
查看>>
炒冷饭系列:设计模式 建造者模式
查看>>
BAT解密:互联网技术发展之路(2)- 业务如何驱动技术发展
查看>>
bat脚本自动扫描制定文件夹下shp文件,并导入数据库,然后执行空间操作
查看>>
关于AsyncHttpClient的cz.msebera.android.httpclient.Header
查看>>
Codekit - 为Web前端打造的全能型神器(附推荐各种工具)
查看>>
JSP JSTL SQL标签操作数据库
查看>>
compare python use py-postgresql & direct pgbench's performance
查看>>
【hibernate框架】核心开发接口-update方法
查看>>
Android过场动画基础教程
查看>>
实现指定任意数量的方块EditText容器BlockEditTextViewGroup
查看>>
PostCSS 常用插件与语法介绍
查看>>
计算机是如何存储数据的?
查看>>
Decorator:从原理到实践,我一点都不虚~
查看>>
前端引用字体@font-face的若干优化方法
查看>>
Linux笔记---修改文件所有者、所属组
查看>>
为什么开发kedis-server
查看>>