react 项目实战,六提取布局组件

重复代码是混乱的根源!,本篇文章我们来继续消灭重复代码。

细心的同学应该能发现:每一个Page组件(/src/pages下的组件)的render方法都拥有相似的jsx结构,比如:

render () {
  return (
    <div>
      <header>
        <h1>...</h1>
      </header>

      <main>
        ...
      </main>
    </div>
  );
}

每一个页面都包含一个页面的标题(header标签和h1标签),并且页面的主要部分都被放在了一个main标签中。

现在很多网站的设计都是如此:大部分页面都有相似的header和footer,不同的是中间部分的内容。

既然是这些部分都是相似的,那么在每一个地方都重复写一遍就显得太没水平了,stupid!

怎么用一份代码来渲染这些相同的地方,并且也能够满足不同的页面之间一些差异化的配置呢(如本文中各页面标题不同)?

传统的MVC Web应用可以通过模板引擎的模板页(layout)来达到这样的效果。

使用React,我们可以使用布局组件来解决这个问题。

布局组件

新建/src/layouts目录用来存放布局组件,新建HomeLayout.js文件:

/**
 * 布局组件
 */
import React from 'react';

class HomeLayout extends React.Component {
  render() {
        // 父组件传递的值
        const { title, children } = this.props;
    return (
      <div>
        <header>
          <h1>{title}</h1>
        </header>

        <main>
          {children}
        </main>
      </div>
    );
  }
}

export default HomeLayout;

我们把每个页面中通用的部分提取到了HomeLayout组件中,在HomeLayout中使用props.title来维护页面的标题文本。

使用props.children来渲染每个页面特有的内容部分。

现在我们可以这样来渲染HomePage:

<HomeLayout title="Welcome">
  <Link to="/user/list">用户列表</Link>
  <br/>
  <Link to="/user/add">添加用户</Link>
</HomeLayout>

HomeLayout里面的内容会作为HomeLayout的props.children渲染到最终的页面上。

重构页面组件

主页

...
import HomeLayout from '../layouts/HomeLayout';

class Home extends React.Component {
  render () {
    return (
      <HomeLayout title="Welcome">
        <Link to="/user/list">用户列表</Link>
        <br/>
        <Link to="/user/add">添加用户</Link>
      </HomeLayout>
    );
  }
}
...

用户添加页面

...
import HomeLayout from '../layouts/HomeLayout';

class UserAdd extends React.Component {
  handleSubmit (e) { ... }
  render () {
    ...
    return (
      <HomeLayout title="添加用户">
        <form onSubmit={(e) => this.handleSubmit(e)}>
          ...
        </form>
      </HomeLayout>
    );
  }
}
...

用户列表页面

...
import HomeLayout from '../layouts/HomeLayout';

class UserList extends React.Component {
  constructor (props) { ... }

  componentWillMount () { ... }

  render () {
    ...
    return (
      <HomeLayout title="用户列表">
        <table>
          ...
        </table>
      </HomeLayout>
    );
  }
}
...

总结

现在我们已经把3个页面组件的重复部分使用HomeLayout来替代了,是不是觉得代码又变得干净了很多呢?

.