本系列讲述在 React 项目的实际开发中,我们如何通过 es6 的特性以及 React 的特性来实现我们的代码重用,今天是第一篇,初级:
试想我们现在有这样一个需求:
这是一个很典型的在登录及注册的业务场景。在这两个页面中,我们可以看到它们之间的相同之处,同时也有一些不同的点,那么简单抽象以下,我们可以将这两个页面按下面的模块来划分。

这样我们就得到了三个组件,分别是
由于 Header 和 Footer 是纯展示性组件,那么我们可以使用 React 的 stateless 组件。由于「登录」与「注册」的标题以及副标题不一样,所以我们需要传递两个 props 值进来,示例代码如下:
import React from "react";const Header = props => {return (<div><h1>{props.title}</h1><h2>{props.subTitle}</h2></div>);};export default Header;
同样的 Footer 的我们也可以使用该方式来剥离成公共组件。不过需要注意的是,与 Header 只有标题和副标题不同的是, Footer 的左侧内容和右侧内容其实是不是固定的,这个时候我们传递进来的 props 需要更灵活,而 Footer 要做的事情是帮传递进来的组件预留位置,此处我们简单以 left 、 right 来区分,示例代码如下:
import React from "react";const Footer = props => {return (<div className="footer"><div className="options">{props.left}</div><div className="options">{props.right}</div></div>);};export default Footer;
这样我们的 Header 和 Footer 就有了,接下来是 Content 区域,与其他两个组件不同的是,Content 里面有个 「登录」或者「注册」按钮,点击后我们需要去触发相关的请求。那这样的组件我们该怎么写,这个时候有两种思路,第一种是组件中将业务逻辑内聚,由于该组件中需要用到 React 的生命周期函数,所以我们使用常规的 React.Component 来创建组件 如下:
import React from "react";class Content extends React.Component {constructor(props) {super(props);this.state = {loading: false};}renderType = type => {if (type === "login") {return (<div><input placeholder="帐号" /><input placeholder="密码" /><input type="submit" value="登录" /></div>);} else if (type === "regist") {return (<div><input placeholder="帐号" /><input placeholder="密码" /><input type="submit" value="注册" /></div>);} else {return null;}};render() {return this.renderType(this.props.type);}}export default Content;
通过将逻辑内聚到组件的好处是我们有很多的状态是可以公用的,比如密码的正则判断等,但是带来的一个坏处是不太友好的扩展性。但是带来的是在业务中使用的简洁性。
最后我们可以简单的将登录注册以以下代码展示:
// Loginfunction Login() {return (<div className="App"><Header title={"登录"} subTitle={"欢迎来到"} /><Content type="login" /><Footer left={'登录'} right="找回密码" /></div>);}// registfunction Regist() {return (<div className="App"><Header title={"注册"} subTitle={"欢迎注册"} /><Content type="regist" /><Footer left={'登录'} right="直接登录" /></div>);}
