简介
组件可能是React中最重要的概念了。它是React的核心构件之一,允许我们将一个用户界面分割成独立的、可重用的部分,使构建用户界面的任务变得更加容易。所有这些独立的组件然后被组合成一个父组件,它将作为我们最终的用户界面。
在本指南中,我们将看一下组件以及它们在React中是如何工作的,我们还将看到如何使用props将数据从一个组件传递到另一个组件。
什么是组件?
组件是一个独立的、可重复使用的代码块,它将用户界面分成小块,而不是在一个文件中构建整个用户界面。按钮、表单、对话框等等都可以被表达为组件。React组件接受任意的输入("props"),并返回React元素或JSX代码,告诉屏幕上应该渲染什么。
为了演示组件是如何工作的,我们把一个Todo应用程序的用户界面分解成各个组件。

这个Todo应用程序是由四个不同的组件组成的,这有助于使代码更容易理解和维护。当构建较大的应用程序时,我们可能会有许多组件,所以拥有结构良好和可读的代码是至关重要的。
**注意:广泛接受的惯例是,所有的组件名称必须以大写字母开头。
React中的组件类型
在React中,主要有两种类型的组件--功能组件和类组件。
功能性组件
这是最简单的创建组件的方式,它是React中的第一种和推荐的组件类型。功能性组件基本上是一个JavaScript/ES6函数,它返回一个特殊的JavaScript语法,称为JSX或React元素。下面的函数是一个有效的功能组件,它接收一个属性对象,通常命名为props。
function Introduction(props) {
return <h1>Hello, I am {props.name}</h1>;
}
另外,我们也可以使用箭头函数符号来创建一个功能组件。
const Introduction = (props) => {
return <h1>Hello, I am {props.name}</h1>;
}
**注意:本质上,这只是另一个JavaScript函数。它与其他普通函数的不同之处在于它的返回值--JXX(JavaScript XML)格式的代码。
组件类
组件类是一个ES6类,它扩展了React组件类,必须有一个render() 方法来返回JSX。如果有必要,它在构造函数中接受道具。
它是组件的第二种类型,主要是因为在旧版本的React中(16.8之前),"状态 "不能在功能组件中使用。因此,功能组件只用于UI渲染,而类组件则用于数据管理和一些额外的操作,如生命周期方法等。然而,随着React钩子的引入,这种情况已经改变,我们现在也可以在功能组件中使用状态。
下面,是同一个Introduction 组件,但这次是作为一个类组件创建的。
class Introduction extends React.Component {
render() {
return <h1>Hello, I am {this.props.name}</h1>;
}
}
**注意:现在我们已经创建了功能组件和类组件,比较一下这两个组件--你可以看到内容基本上是一样的。
在React中使用组件
到目前为止,我们已经看到了如何创建一个功能组件或类组件。现在,让我们来看看我们如何在父级组件中使用这些组件。为了以后能够使用一个组件(或在一个父组件中),我们必须首先导出它,以便我们能够在其他地方导入它。
const Introduction = (props) => {
return <h1>Hello, I am {props.name}</h1>;
}
export default Introduction;
导入后,我们就可以在父组件(在本例中是App 组件)中引用它了。
import Introduction from './Introduction';
const App = () => {
return (
<div className="App">
<Introduction name="John Doe" />
</div>
);
}
通过道具向组件中传递数据
当我们使用create-react-app 命令安装React时,我们会在App.js 文件中自动得到一个功能组件,作为我们应用程序的起点。当我们构建应用程序时,我们的大部分数据很可能驻留在App.js 文件中,而我们无疑希望将这些数据传递给新的组件(子组件)。Props,也就是 "属性 "的意思,是用来完成这个任务的。
这是React中的一个重要概念,它允许组件之间相互交流。Props是只读的,所以它们只能向一个方向传输数据(从父组件到子组件)。Props不允许数据从子组件传递到父组件,也不允许从组件传递到同一级别的组件。
现在让我们创建一个Button 组件,然后把不同的按钮的名字作为道具传入。
const Button = (props) => {
return (
<div>
<button class="btn">{props.name}</button>
</div>
);
};
export default Button;
让我们回到App.js 文件,看看我们如何使用props向按钮组件传递数据。我们需要做的就是在Button 组件上定义一个道具,并给它赋值。
import Button from './Button';
const App = () => {
return (
<div className="App">
<h1>Hello World</h1>
<Button name="Login" />
<Button name="Logout" />
<Button name="Sign Up" />
</div>
);
};
export default App;
**注意:**我们必须导入该组件,才能在父组件中使用它。

道具可以用来传递任何类型的数据,包括数组和对象,所以它们的用途是没有限制的。
将一个应用程序分割成多个组件
在我们总结本指南之前,让我们看看一个由学生详情和分数详情组成的StudentInfo 组件的例子。
const StudentInfo = (props) => {
return (
<div className="student">
<div className="student-info">
<img
className="Avatar"
src={props.student.image}
alt={props.student.name}
/>
<div className="student-name-info">
<p>{props.student.name}</p>
<p>{props.student.userName}</p>
</div>
</div>
<div className="score-details">
<div className="Comment-text">{props.score}</div>
<div className="Comment-date">{props.remark}</div>
</div>
</div>
);
};
export default StudentInfo;
这需要一个含有大量信息的student 对象(作为道具),并描述一个学生卡,以显示学生的详细信息以及学生的分数和评论。由于嵌套的原因,这个组件很难改变,也很难重复使用其中的个别部分。
让我们从中提取一个组件,那就是StudentInfo 部分。
const StudentInfo = (props) => {
return (
<div className="student-info">
<img
className="Avatar"
src={props.student.image}
alt={props.student.name}
/>
<div className="student-name-info">
<p>{props.student.name}</p>
<p>{props.student.userName}</p>
</div>
</div>
);
};
export default StudentInfo;
我们现在可以将父级组件简化成这样
import StudentInfo from './StudentInfo';
const StudentInfo = (props) => {
return (
<div className="student">
<StudentInfo student="props.student" />
<div className="score-details">
<div className="Comment-text">{props.score}</div>
<div className="Comment-date">{props.remark}</div>
</div>
</div>
);
};
export default StudentInfo;
提取组件一开始可能显得很无聊,但拥有一个可重用组件的集合对我们在大型应用中是有好处的。
总结
在本指南中,我们已经能够了解到组件在React中是如何工作的,两种类型的组件以及如何使用props将数据从一个组件传递到另一个组件。