Components和Props

Components使得UI被划分为一个个独立、可复用的零件,并单独考虑每个零件。
在概念上,组件就像是JavaScript函数。他们接受任意的输入(称为"props"),并返回React elements来描述屏幕上应该出现的内容。

函数式Components和class Components

定义一个Component最简单的方法就是写个JavaScript函数:

function Welcome(props) {
  return 

Hello, {props.name}

; }

这个函数是一个有效的React component,因为他接受一个名为'props'对象的参数,并且返回一个React element。我们称这种组件为'函数式'的,因为他们就是普通的JavaScript函数。
你也可以用一个ES6 class来定义component:

class Welcome extends React.Component {
  render() {
    return 

Hello, {this.props.name}

; } }

从React的角度来看,上面这两个components是相同的。
我们将在下一节讨论,Classes方式中的一些额外特性。在那之前,方便起见,我们将使用函数式的components。

渲染Component

之前,我们至于见过表现DOM标签的React elements:

const element = 
;

不仅如此,elements也可以表示用户自定义的components:

const element = 

当React发现一个表示用户自定义组件的element,它会把JSX属性作为一个单独的对象传给这个component。我们将这个对象成为'props'。
举个例子,下面的代码在页面上渲染出"Hello, Sara":

function Welcome(props) {
  return 

Hello, {props.name}

; } const element = ; ReactDOM.render( element, document.getElementById('root') );

在CodePen上试试看
让我们重新过一遍这个例子中发生了什么:

  1. 我们调用ReactDOM.render()函数去渲染element:
  2. React调用Wecome组件,将{name: 'Sara'}作为props。
  3. 我们的Welcome组件返回一个element:

    Hello, Sara

    作为结果。
  4. React DOM高效地更新DOM来匹配

    Hello, Sara

警告:
component名字的首字母始终都是大写。
比如,

表示一个DOM标签,但是表示一个component,而且需要将Welcome加入当前范围内。

组合Components

Components可以在他们的输出中引用其他的components。这样我们就可以使用相同的组件来叠加完成任意的细节。按钮,表单,对话框和屏幕,在React应用中,这些通常都表示为组件。
比如:我们可以创建一个App组件用来渲染多个Welcome

function Welcome(props) {
  return 

Hello, {props.name}

; } function App() { return (
); } ReactDOM.render( , document.getElementById('root') );

在CodePen上试一试
通常,新的React应用在最上层有一个单独的App组件。但是如果你将React集成到现有的应用中,你可以自下而上,从一个小的component开始,比如一个按钮,逐步的整合到层次结构的顶层。

警告:
Components必须返回一个单独的根element。这就是为什么我们添加一个

来包括所有的 elements。

提取Components

大胆的将components分割成更小的components。
比如,考虑这个Comment component:

function Comment(props) {
  return (
    
{props.author.name}
{props.author.name}
{props.text}
{formatDate(props.date)}
); }

在CodePen上试一试
它接收author(一个object),text(一个字符串)和date(一个date)作为props,描述了社交媒体网站上一则评论。
由于全是嵌套,这个component很难改变,而且也很难去重用他的各个部分。让我们从中提取几个组件。
首先,我们来提取Avatar:

function Avatar(props) {
  return (
    {props.user.name}
  );
}

Avatar不需要知道Comment里面究竟在渲染什么东西。因此我们传给prop一个更为通用的名字:user,而不是author
我们建议从组件自身的观点来命名props,而不是依据组件所在的环境。
现在我们就稍微简化了下Comment:

function Comment(props) {
  return (
    
{props.author.name}
{props.text}
{formatDate(props.date)}
); }

接下来,我们将提取一个UserInfo组件,他渲染一个Avatar和用户的名字:

function UserInfo(props) {
  return (
    
{props.user.name}
); }

这使得我们可以进一步简化Comment:

function Comment(props) {
  return (
    
{props.text}
{formatDate(props.date)}
); }

在CodePen上试一试
提取components也许乍看之下像是无用功,但在大型的app中,能有一系列可重用的组件,这么做绝对超值。一个很好的经验法则:如果你的UI中某部分被重复使用多次(按钮,面板,头像),或者自身相当复杂(App,FeedStory,评论), 这都是成为可重用组件的最佳人选。

Props是只读的

不论你将component声明为函数还是类,都绝不能去修改它的props。看下这个sum函数:

function sum(a, b) {
  return a + b;
}

这样的函数我们称其为"pure",因为他们不回去改变输入,且对于输入一样返回的结果始终都是相同的。
相比之下,这个函数不是纯函数,因为它改变了自己的输入:

function withdraw(account, amount) {
  account.total -= amount;
}

React虽然相当灵活,但它有一个严格的规则:
所有的React组件必须像个纯函数一样,不得修改他们的props。
当然,应用的UI是动态的,随着事件而变化。在下一节,我们将引入一个新的概念:"state"。State使得React components可以根据用户的行为,网络响应或者其他什么,使得他们的输出每次不同,而不会违反此规则。

你可能感兴趣的:(Components和Props)