# 03. 组件 & Props
# 函数组件与 class 组件
# 1.函数组件
function Welcome(props){
return <h1>Hello, {props.name}</h1>
}
该函数是一个有效的React组件。接收唯一带有数据的props参数,并返回一个React元素。
# 2.class组件
使用ES6的class来定义:
class Welcome extends React.Component{
// render 方法描述你想在屏幕看到的内容
render() {
return <h1>Hello, {this.props.name}</h1>
}
}
以上两个组件是等效的。
# 函数组件与Class组件在事件处理上的一些区别
使用
class组件
时的事件处理:onClick={() => this.props.onClick()}
使用
函数组件
时的事件处理:onClick={props.onClick}
(注意两侧都没有括号)。
# 渲染组件(父子组件传值)
React 元素也可以是用户自定义的组件:
const element = <Welcome name="Sara" />;
通过属性(attributes)来传递值给子组件:
function Welcome(props) { // 通过props接收传入值
return <h1>Hello, {props.name}</h1>;
}
const element = <Welcome name="Sara" />; // 通过attributes传入值
ReactDOM.render(
element,
document.getElementById('root')
);
注意: 组件名称必须以大写字母开头。
React 会将以小写字母开头的组件视为原生 DOM 标签。例如,<div />
代表 HTML 的 div 标签,而 <Welcome />
则代表一个组件,并且需在作用域内使用 Welcome
。
# 组合组件(复用组件)
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
function App() {
return (
<div>
// 复用Welcome组件
<Welcome name="Sara" />
<Welcome name="Cahal" />
<Welcome name="Edite" />
</div>
);
}
ReactDOM.render(
<App />,
document.getElementById('root')
);
通常来说,每个新的 React 应用程序的顶层组件都是
App
组件
# 提取组件(拆分组件)
参考如下 Comment
组件:
function Comment(props) {
return (
<div className="Comment">
<div className="UserInfo">
<img className="Avatar"
src={props.author.avatarUrl}
alt={props.author.name}
/>
<div className="UserInfo-name">
{props.author.name}
</div>
</div>
<div className="Comment-text">
{props.text}
</div>
<div className="Comment-date">
{formatDate(props.date)}
</div>
</div>
);
}
该组件由于嵌套的关系,变得难以维护,且很难复用它的各个部分。因此,让我们从中提取一些组件出来。
首先,提取 Avatar
组件:
function Avatar(props) {
return (
<img className="Avatar"
src={props.user.avatarUrl}
alt={props.user.name}
/>
);
}
# props命名原则
Avatar
不需知道它在 Comment
组件内部是如何渲染的。因此,我们给它的 props 起了一个更通用的名字:user
,而不是 author
。
我们建议从组件自身的角度命名 props,而不是依赖于调用组件的上下文命名。
接下来,我们将提取 UserInfo
组件,该组件在用户名旁渲染 Avatar
组件:
function UserInfo(props) {
return (
<div className="UserInfo">
<Avatar user={props.user} />
<div className="UserInfo-name">
{props.user.name}
</div>
</div>
);
}
最终的 Comment
组件:
function Comment(props) {
return (
<div className="Comment">
<UserInfo user={props.author} />
<div className="Comment-text">
{props.text}
</div>
<div className="Comment-date">
{formatDate(props.date)}
</div>
</div>
);
}
最初看上去,提取组件可能是一件繁重的工作,但是,在大型应用中,构建可复用组件库是完全值得的。
# 提取原则
- UI中多次被使用的部分
- 一个足够复杂的组件(页面)
# Props 的只读性(不能修改Props)
组件无论是使用函数声明还是通过 class 声明 (opens new window),都决不能修改自身的 props。
当然,应用程序的 UI 是动态的,并会伴随着时间的推移而变化。在下一章节 (opens new window)中,我们将介绍一种新的概念,称之为 “state”。在不违反上述规则的情况下,state 允许 React 组件随用户操作、网络响应或者其他变化而动态更改输出内容