Skip to content

Latest commit

 

History

History
255 lines (196 loc) · 7.18 KB

【译】快速起步-组件与属性.md

File metadata and controls

255 lines (196 loc) · 7.18 KB
title date version
快速起步-组件与属性
2017-04-14 09:01:04 -0700
15.5.0

组件与属性

组件允许您将UI拆分为多个独立的,可重用的部分。

概念上,组件就类似于 JavaScript 函数。它们接收任意的输入(props),返回用于描述屏幕显示内容的 React elements

函数式组件和类组件

最简单定义组件的方式,是编写一个 JavaScript 函数:

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

这个函数是一个合法的组件,因为它接收包含数据的单个 props 对象参数,返回了一个 React elements。我们称这种用JavaScript函数定义的组件为函数式组件。

你也可以使用 ES6 class 来定义组件:

class Welcome extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}

上述两个组件在视图展示上是等同的。

下一章节 我们会讨论类组件的一些附加特性。在这之前,我们先使用函数式组件来简化演示。

渲染组件

之前,我们仅仅遇到表示DOM标签的 React elements

const element = <div />;

然而,元素也可以表示用户定义的组件:

const element = <Welcome name="Sara" />;

React 发现元素表示一个用户定义的组件时,它将 JSX 属性作为单个对象传递给组件。我们称之为 props

例如,以下代码在页面上渲染 "Hello, Sara":

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

const element = <Welcome name="Sara" />;
ReactDOM.render(
  element,
  document.getElementById('root')
);

CodePen Demo

我们回顾下这个例子中发生了什么:

  1. 使用 <Welcome name="Sara" /> 元素调用 ReactDOM.render()
  2. React 将 {name: 'Sara'} 作为属性调用 Welcome 组件。
  3. Welcome 组件将 <h1>Hello, Sara</h1> 元素作为结果返回。
  4. React DOM 使用 <h1>Hello, Sara</h1> 来更新DOM。

警告:

总是用大写字母开头命名自定义组件

例如, <div /> 表示一个DOM标签,但是 <Welcome /> 表示一个组件,且需要作用域中存在 Welcome 变量。

复合组件

组件可以在其输出中引用其他组件。这使我们可以对不同级别的实现抽象为相同的组件。在 React 中,按钮、表单、对话框,屏幕都通常被抽象为组件。

例如,我们可以创建 App 组件来渲染多个 Welcome 组件:

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

function App() {
  return (
    <div>
      <Welcome name="Sara" />
      <Welcome name="Cahal" />
      <Welcome name="Edite" />
    </div>
  );
}

ReactDOM.render(
  <App />,
  document.getElementById('root')
);

CodePen Demo

通常,新的React应用程序在最顶层都会有一个 App 组件。然而,如果你集成 React 到一个现有的应用程序,你可以在内部先使用像 Button 这样的小部件,然后逐步的替换到最顶层。

警告:

组件必须返回单个根元素。这是为什么我们用 <div> 来包含多个 <Welcome /> 组件。

提取组件

不要害怕将组件分成更小的组件。

例如,思考这个 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>
  );
}

CodePen Demo

它接收 author(对象类型),text(字符串)和 date(日期) 作为属性,然后在社交网站上呈现一个评论。

由于多层嵌套,这个组件很难变化,且很难重用它其中的各个部分。我们可以从中提取几个组件。

首先,我们提取 Avatar 组件:

function Avatar(props) {
  return (
    <img className="Avatar"
      src={props.user.avatarUrl}
      alt={props.user.name}
    />
  );
}

Avatar 不需要知道谁会渲染它。这也是为什么我们使用 user 这个更通用的属性名称来替代 author

我们建议从组件自身的角度来命名属性,而不是它的使用者。

我们现在已经稍微简化了一下 Comment 组件:

function Comment(props) {
  return (
    <div className="Comment">
      <div className="UserInfo">
        <Avatar user={props.author} />
        <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>
  );
}

下一步,我们将提取 UserInfo 组件,用于在用户名旁边显示 Avator

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>
  );
}

CodePen Demo

提取组件可能是看起来很繁琐的工作,但是在较大的应用程序中,可重用的组件能够付出更小的代价。 如果您的UI的一部分使用了几次(按钮,面板,头像)或者它自身就很复杂(App, Comment),它们则是拆分出可重用组件的最佳候选人,这是一个相当实用的经验法则。

属性是只读的

当你定义一个组件时,它不应该修改自己的 props。思考下面的 sum 函数。

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

这些不会修改输入参数,且当输入参数相同时,总是返回相同结果的函数被称之为 纯函数

相比之下,以下的函数是不纯的,因为它改变了自己的输入:

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

React 非常灵活,但是也有一个严格的规则:

所有的React组件必须像纯函数那样使用 props(也就是不要在组件内部修改 props

当然,应用程序的UI是动态的,可以随时间的推移而变化。在 下一节 中,我们将介绍新的概念 statestate 允许React组件根据用户操作,网络响应以及其他随时间推移产生的变化来修改组件输出,而不会违背该规则。