本系列讲述在 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;
通过将逻辑内聚到组件的好处是我们有很多的状态是可以公用的,比如密码的正则判断等,但是带来的一个坏处是不太友好的扩展性。但是带来的是在业务中使用的简洁性。
最后我们可以简单的将登录注册以以下代码展示:
// Login
function Login() {
return (
<div className="App">
<Header title={"登录"} subTitle={"欢迎来到"} />
<Content type="login" />
<Footer left={'登录'} right="找回密码" />
</div>
);
}
// regist
function Regist() {
return (
<div className="App">
<Header title={"注册"} subTitle={"欢迎注册"} />
<Content type="regist" />
<Footer left={'登录'} right="直接登录" />
</div>
);
}