今天看啥  ›  专栏  ›  DYS1230

React项目实践系列三

DYS1230  · 掘金  ·  · 2018-06-20 06:08

React项目实践系列三

数据分析平台-实践系列三

本章讲解项目目录结构的搭建,路由模式选择和代码分割

目录结构

目前项目结构的划分如图

由于项目并非十分庞大,因此按照功能划分。(涉及Redux的文章会后期写)

| -- api  # 后台接口
| -- components  # 公共组件
    | -- commonA
        | -- index.js
        | -- index.less
| -- config  # 项目配置项
    | -- constant.js # 项目常量
| -- font # 字体图标文件
| -- redux
    | -- store.js
    | -- pageA # 与containers对应
        | -- action-type.js
        | -- actionA.js
        | -- actionB.js
        | -- reducer.js
    | -- pageB
        | -- action-type.js
        | -- actionA.js
        | -- actionB.js
        | -- reducer.js
| -- router # 项目一级路由
| -- utils # 项目工具函数
| -- containers
        | -- pageA
             | -- components # 展示组件
                     | -- A1
                           | -- index.js
                           | -- index.less
             | -- index.js
             | -- index.less
             | -- Xcontainer.js # 容器组件
             | -- Ycontainer.js
        | -- pageB
             | -- components # 展示组件
                     | -- A1
                           | -- index.js
                           | -- index.less
             | -- index.js
             | -- index.less
             | -- Xcontainer.js # 容器组件
             | -- Ycontainer.js
| -- index.js # 入口文件
| -- index.less

目前开发保证几个原则:

  1. 页面开发。目前项目页面并不算多,仅有接近二十个页面。在containers文件夹中前期区分好容器组件及展示组件。当写到一定程度,拆分出项目的公共组件,放入components文件夹中。
  2. 状态管理。在Redux文件夹中,直接对应了每个container。在store.js中使用combineReducers整合所有页面的reducer。其后每个页面引用其的action就可以了,对于所有的数据处理,全在action.js中进行。
  3. 路由管理。由于使用的为React Router 4,其不推荐集中路由,组件在哪里匹配就在哪里渲染。因此只定义了一个项目一级路由。

然而由于前期未对项目的复杂度进行合理估计。这套目录结构随着业务发展,已经渐渐有些不够合理。后期项目对于目录结构需要进行重构,不以功能划分,需混合,以业务划分。

建立modules目录,按照业务指定其的containercomponentrouterservice等。且遵从就近依赖,将actionreducer置于对应的container中。

路由模式

页面为单页面应用,因此所有路由是由前端控制。路由使用的是React Router,有两种路由可以选择:hashHistory以及browserHistory

hashHistory是根据#后的路径进行处理,而browserHistory则是我们同常情况下的页面访问路径。如使用hashHistory,路径为www.abc.com/#/helloWorldbrowserHistorywww.abc.com/helloWorld

一般下,两种模式都可以,但是由于个人十分介意多了个#符号,因此选用browserHistory。使用browserHistory需要后端进行配合,因为如果后台没有进行正确配置,如果直接访问www.abc.com/helloWorld会像后台发起请求,返回404。

配置例子在Vue Router中有几个例子。而该项目,后台在开发环境下使用Tomcat,需要修改web.xml文件。

...
<error-page>
    <error-code>404</error-code>
    <location>/index.html</location>
</error-page>
...

代码分割

代码分割是webpack最引人注目的功能之一,它可以让我们实现代码的按需加载。其最多的使用情况是基于路由的分割。使用import()语法可实现动态加载js,实现代码按需加载。import()返回的为Promise,我们定义一个高阶组件。

function asyncComponent(importComponent) {
    class AsyncComponent extends Component {
        constructor(props) {
            super(props);

            this.state = {
                component: null
            };
        }

        async componentDidMount() {
            const { default: component } = await importComponent(); // 当引入组件时才动态加载js

            this.setState({component});
        }

        render() {
            const C = this.state.component;

            return C ? <C {...this.props} /> : null;
        }
    }

    return AsyncComponent;
}

实现按需加载

const Hello = asyncComponent(() => import('../Hello'));

...
	<Switch>
		<Route path="/hello" component={Hello} />
		...
	</Switch>
...

当访问/hello时,打开network,可看到动态加载了一个javascript文件。若对其原理感兴趣,可看这篇文章,其最根本的原理就是动态添加script标签。




原文地址:访问原文地址
快照地址: 访问文章快照