本系列讲述在 React 项目的实际开发中,我们如何通过 es6 的特性以及 React 的特性来实现我们的代码重用,今天是第一篇,初级:

    试想我们现在有这样一个需求:
    React 中如何复用代码?(一) - 图1

    这是一个很典型的在登录及注册的业务场景。在这两个页面中,我们可以看到它们之间的相同之处,同时也有一些不同的点,那么简单抽象以下,我们可以将这两个页面按下面的模块来划分。

    React 中如何复用代码?(一) - 图2

    这样我们就得到了三个组件,分别是

    由于 Header 和 Footer 是纯展示性组件,那么我们可以使用 React 的 stateless 组件。由于「登录」与「注册」的标题以及副标题不一样,所以我们需要传递两个 props 值进来,示例代码如下:

    1. import React from "react";
    2. const Header = props => {
    3. return (
    4. <div>
    5. <h1>{props.title}</h1>
    6. <h2>{props.subTitle}</h2>
    7. </div>
    8. );
    9. };
    10. export default Header;

    同样的 Footer 的我们也可以使用该方式来剥离成公共组件。不过需要注意的是,与 Header 只有标题和副标题不同的是, Footer 的左侧内容和右侧内容其实是不是固定的,这个时候我们传递进来的 props 需要更灵活,而 Footer 要做的事情是帮传递进来的组件预留位置,此处我们简单以 left 、 right 来区分,示例代码如下:

    1. import React from "react";
    2. const Footer = props => {
    3. return (
    4. <div className="footer">
    5. <div className="options">{props.left}</div>
    6. <div className="options">{props.right}</div>
    7. </div>
    8. );
    9. };
    10. export default Footer;

    这样我们的 Header 和 Footer 就有了,接下来是 Content 区域,与其他两个组件不同的是,Content 里面有个 「登录」或者「注册」按钮,点击后我们需要去触发相关的请求。那这样的组件我们该怎么写,这个时候有两种思路,第一种是组件中将业务逻辑内聚,由于该组件中需要用到 React 的生命周期函数,所以我们使用常规的 React.Component 来创建组件 如下:

    1. import React from "react";
    2. class Content extends React.Component {
    3. constructor(props) {
    4. super(props);
    5. this.state = {
    6. loading: false
    7. };
    8. }
    9. renderType = type => {
    10. if (type === "login") {
    11. return (
    12. <div>
    13. <input placeholder="帐号" />
    14. <input placeholder="密码" />
    15. <input type="submit" value="登录" />
    16. </div>
    17. );
    18. } else if (type === "regist") {
    19. return (
    20. <div>
    21. <input placeholder="帐号" />
    22. <input placeholder="密码" />
    23. <input type="submit" value="注册" />
    24. </div>
    25. );
    26. } else {
    27. return null;
    28. }
    29. };
    30. render() {
    31. return this.renderType(this.props.type);
    32. }
    33. }
    34. export default Content;

    通过将逻辑内聚到组件的好处是我们有很多的状态是可以公用的,比如密码的正则判断等,但是带来的一个坏处是不太友好的扩展性。但是带来的是在业务中使用的简洁性。

    最后我们可以简单的将登录注册以以下代码展示:

    1. // Login
    2. function Login() {
    3. return (
    4. <div className="App">
    5. <Header title={"登录"} subTitle={"欢迎来到"} />
    6. <Content type="login" />
    7. <Footer left={'登录'} right="找回密码" />
    8. </div>
    9. );
    10. }
    11. // regist
    12. function Regist() {
    13. return (
    14. <div className="App">
    15. <Header title={"注册"} subTitle={"欢迎注册"} />
    16. <Content type="regist" />
    17. <Footer left={'登录'} right="直接登录" />
    18. </div>
    19. );
    20. }