绘制用户界面(UI)

React 是一个用于渲染用户界面(UI)的 JavaScript 工具库。UI 是由类似按钮(buttons)、文本框(text)以及图片(images)之类的小零件构成的。React 能够让你将这些“小零件”组合成可重复利用、可嵌套的 组件(components)。从网站到手机应用,屏幕上的所有内容都可以拆解成组件。在本章中,你将学习到如何创建、自定义以及根据条件显示 React 组件。

你的第一个组件

React 应用程序是由被称为“组件(components)”的独立的 UI 片段构成的。一个 React 组件就是一个 JavaScript 函数,并且函数中可以添加 markup。组件可以小刀一个按钮,也可以大到整个页面。下面展示的是一个 Gallery 组件,其中渲染了三个 Profile 组件:

function Profile() {
  return (
    <img
      src="https://i.imgur.com/MK3eW3As.jpg"
      alt="Katherine Johnson"
    />
  );
}

export default function Gallery() {
  return (
    <section>
      <h1>Amazing scientists</h1>
      <Profile />
      <Profile />
      <Profile />
    </section>
  );
}

Ready to learn this topic?

请阅读 你的第一个组件 章节以了解如何声明和使用 React 组件。

Read More

导入(Import)和导出(exporing)组件

你可以在一个文件中声明多个组件,但是文件变得太大的话就不方便查看了。要解决此问题,你可以将一个组件放到一个单独的文件中并(导出) export 组件,然后在另一个文件中(导入) import 该组件:

import Profile from './Profile.js';

export default function Gallery() {
  return (
    <section>
      <h1>Amazing scientists</h1>
      <Profile />
      <Profile />
      <Profile />
    </section>
  );
}

Ready to learn this topic?

请阅读 导入(import)和导出(export)组件 章节以了解组合拆分组件。

Read More

用 JSX 书写 markup

每个 React 组件就是 JavaScript 函数,函数中可以书写 markup,这些 markup 将由 React 渲染到浏览器中。React 组件使用名为 JSX 的语法扩展来支持 markup。JSX 看上去就像 HTML 一样,但它的语法比较严格,并且可以显示动态信息。

如果我们将现有的 HTML markup 粘贴到 React 组件中,可能会报错:

export default function TodoList() {
  return (
    // This doesn't quite work!
    <h1>Hedy Lamarr's Todos</h1>
    <img
      src="https://i.imgur.com/yXOvdOSs.jpg"
      alt="Hedy Lamarr"
      class="photo"
    >
    <ul>
      <li>Invent new traffic lights
      <li>Rehearse a movie scene
      <li>Improve spectrum technology
    </ul>
  );
}

如果你已有上述类似的 HTML 了,可以使用 converter 工具来修复语法错误:

export default function TodoList() {
  return (
    <>
      <h1>Hedy Lamarr's Todos</h1>
      <img
        src="https://i.imgur.com/yXOvdOSs.jpg"
        alt="Hedy Lamarr"
        className="photo"
      />
      <ul>
        <li>Invent new traffic lights</li>
        <li>Rehearse a movie scene</li>
        <li>Improve spectrum technology</li>
      </ul>
    </>
  );
}

Ready to learn this topic?

请阅读 用 JSX 书写 Markup 章节以了解如何编写有效的 JSX 代码。

Read More

JavaScript in JSX with curly braces

JSX 允许你在 JavaScript 文件中书写类似 HTML 的标记,使渲染逻辑和内容处于同一位置。有时,你需要添加一点 JavaScript 逻辑或者在 markup 中引用一个动态属性。在这种情况下,你可以在 JSX 中使用大花括号为 JavaScript “开一扇窗”:

const person = {
  name: 'Gregorio Y. Zara',
  theme: {
    backgroundColor: 'black',
    color: 'pink'
  }
};

export default function TodoList() {
  return (
    <div style={person.theme}>
      <h1>{person.name}'s Todos</h1>
      <img
        className="avatar"
        src="https://i.imgur.com/7vQD0fPs.jpg"
        alt="Gregorio Y. Zara"
      />
      <ul>
        <li>Improve the videophone</li>
        <li>Prepare aeronautics lectures</li>
        <li>Work on the alcohol-fuelled engine</li>
      </ul>
    </div>
  );
}

Ready to learn this topic?

请阅读 通过花括号在 JSX 中书写 JavaScript 章节以了解如何在 JSX 中访问 JavaScript 数据。

Read More

将属性(props)传递给组件

React 组件使用 props 参数来互相通信。每个父组件都可以通过 props 将信息传递给子组件。props 可能会让你联想到 HTML 中的属性(attributes),但是你可以通过 props 传递 JavaScript 所支持的不同类型的值,包括对象(objects)、数组(array)、函数(functions)甚至 JSX!

import { getImageUrl } from './utils.js'

export default function Profile() {
  return (
    <Card>
      <Avatar
        size={100}
        person={{
          name: 'Katsuko Saruhashi',
          imageId: 'YfeOqp2'
        }}
      />
    </Card>
  );
}

function Avatar({ person, size }) {
  return (
    <img
      className="avatar"
      src={getImageUrl(person)}
      alt={person.name}
      width={size}
      height={size}
    />
  );
}

function Card({ children }) {
  return (
    <div className="card">
      {children}
    </div>
  );
}

Ready to learn this topic?

请阅读 向组件传递 Props 章节以了解如何传递并读取 props。

Read More

按条件渲染

组件通常需要根据不同的条件显示不同的内容。在 React 中,你可以使用诸如 if 语句、&& 以及 ? : 操作符等控制渲染 JSX 的条件。

在本示例中,JavaScript 的 && 操作符被用于控制在什么条件下渲染复选框(checkmark):

function Item({ name, isPacked }) {
  return (
    <li className="item">
      {name} {isPacked && '✔'}
    </li>
  );
}

export default function PackingList() {
  return (
    <section>
      <h1>Sally Ride's Packing List</h1>
      <ul>
        <Item
          isPacked={true}
          name="Space suit"
        />
        <Item
          isPacked={true}
          name="Helmet with a golden leaf"
        />
        <Item
          isPacked={false}
          name="Photo of Tam"
        />
      </ul>
    </section>
  );
}

Ready to learn this topic?

请阅读Read 按条件渲染 章节以了解根据不同的条件来渲染内容。

Read More

渲染列表

你通常需要按照数据集合来显示多个相似的组件。这是,你可以将 React 和 JavaScript 的 filter()map() 函数一同使用,以便将数据中的数组转换为组件数组。

对于每一个数组项,你需要指定一个 key(键)。通常,你会使用数据库中的 ID 作为 key 使用。key 的作用是让 React 保持对列表中每个条目的追踪,即便列表发生了变化,也依然能够追踪每个条目在列表中的位置。

import { people } from './data.js';
import { getImageUrl } from './utils.js';

export default function List() {
  const listItems = people.map(person =>
    <li key={person.id}>
      <img
        src={getImageUrl(person)}
        alt={person.name}
      />
      <p>
        <b>{person.name}:</b>
        {' ' + person.profession + ' '}
        known for {person.accomplishment}
      </p>
    </li>
  );
  return (
    <article>
      <h1>Scientists</h1>
      <ul>{listItems}</ul>
    </article>
  );
}

Ready to learn this topic?

且阅读 渲染列表 章节以了解如何渲染组件列表以及如何选择 key(键)。and how to choose a key.

Read More

保持组件的功能单一

某些 JavaScript 函数是很 “pure(纯粹的)”。一个“纯粹的”函数有如下特点:

  • 只管好自己的事。 在被调用时,不会更改已经存在的任何对象(objects)或变量。
  • 相同的输入,相同的输出。 给定相同的输入,“纯粹的”函数是能够始终返回相同结果的。

通过严格的将组件编写为“纯粹的”函数,你就可以避免在代码库膨胀时出现一系列令人费解的错误和不可预测的行为。以下示例展示的是一个“不纯粹的”组件:

let guest = 0;

function Cup() {
  // Bad: changing a preexisting variable!
  guest = guest + 1;
  return <h2>Tea cup for guest #{guest}</h2>;
}

export default function TeaSet() {
  return (
    <>
      <Cup />
      <Cup />
      <Cup />
    </>
  )
}

你可以通过传递 prop 而不是修改已存在的变量,让此组件变为“纯粹的”组件:

function Cup({ guest }) {
  return <h2>Tea cup for guest #{guest}</h2>;
}

export default function TeaSet() {
  return (
    <>
      <Cup guest={1} />
      <Cup guest={2} />
      <Cup guest={3} />
    </>
  );
}

Ready to learn this topic?

请阅读 保持组件的功能单一 章节以了解如何将组建编写为“纯粹的”、可预测的函数。

Read More

接下来干什么?

请转到 你的第一个组件 章节并逐章节阅读吧!

或者,如果你已经熟悉这些内容了,为何不去阅读 添加交互性 呢?