描述UI
React 是一个用于呈现用户界面 (UI) 的 JavaScript 库。 UI 由按钮、文本和图像等小单元构建而成。 React 允许您将它们组合成可重用、可嵌套的组件。 从网站到手机应用程序,屏幕上的一切都可以分解成组件。 在本章中,您将学习创建、自定义和有条件地显示 React 组件。
本章内容预告
- 如何编写你的第一个 React 组件
- 何时以及如何创建多组件文件
- 如何使用 JSX 向 JavaScript 添加标记
- 如何在 JSX 中使用花括号从组件中访问 JavaScript 功能
- 如何使用 props 配置组件
- 如何有条件地渲染组件
- 如何一次渲染多个组件
- 如何通过保持组件纯净来避免混淆错误
你的第一个组件
React 应用程序是由称为组件的独立 UI 部分构建的。 React 组件是一个 JavaScript 函数,您可以在其中添加标记。 组件可以小到一个按钮,也可以大到整个页面。 这是一个 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>
);
}
准备好学习这个主题了吗?
阅读你的第一个组件以了解如何声明和使用 React 组件。
导入和导出组件
您可以在一个文件中声明多个组件,但大文件可能难以导航。 要解决这个问题,您可以将一个组件导出到它自己的文件中,然后从另一个文件中导入该组件:
Profile.js
export default function Profile() {
return (
<img
src="https://i.imgur.com/QIrZWGIs.jpg"
alt="Alan L. Hart"
/>
);
}
Gallery.js
import Profile from './Profile.js';
export default function Gallery() {
return (
<section>
<h1>Amazing scientists</h1>
<Profile />
<Profile />
<Profile />
</section>
);
}
准备好学习这个主题了吗?
阅读导入和导出组件以了解如何将组件拆分到它们自己的文件中。
使用JSX写标记
每个 React 组件都是一个 JavaScript 函数,其中可能包含 React 呈现到浏览器中的一些标记。 React 组件使用称为 JSX 的扩展语法来表示该标记。 JSX 看起来很像 HTML,但更严格一些,并且可以显示动态信息。
如果我们将现有的 HTML 标记粘贴到 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>
);
}
Error
/App.js: Adjacent JSX elements must be wrapped in an enclosing tag. Did you want a JSX fragment <>...</>? (5:4)
3 | // This doesn't quite work!
4 | <h1>Hedy Lamarr's Todos</h1>
> 5 | <img
| ^
6 | src="https://i.imgur.com/yXOvdOSs.jpg"
7 | alt="Hedy Lamarr"
8 | class="photo"
如果您有这样的现有 HTML,您可以使用转换器修复它:
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>
</>
);
}
准备好学习这个主题了吗?
阅读使用 JSX 编写标记以了解如何编写有效的 JSX。
JSX 中带有花括号的 JavaScript
JSX 允许您在 JavaScript 文件中编写类似 HTML 的标记,将呈现逻辑和内容保持在同一位置。 有时您会希望在该标记内添加一些 JavaScript 逻辑或引用动态属性。 在这种情况下,您可以在 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>
);
}
准备好学习这个主题了吗?
阅读JSX 中带有花括号的 JavaScript了解如何从 JSX 访问 JavaScript 数据。
将 props 传递给组件
React 组件使用 props 相互通信。 每个父组件都可以通过给它们 props 将一些信息传递给它的子组件。 Props 可能会让你想起 HTML 属性,但你可以通过它们传递任何 JavaScript 值,包括对象、数组、函数,甚至 JSX!
App.js
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>
);
}
utils.js
export function getImageUrl(person, size = 's') {
return (
'https://i.imgur.com/' +
person.imageId +
size +
'.jpg'
);
}
准备好学习这个主题了吗?
阅读将props传递给组件以了解如何传递和读取props。
条件渲染
您的组件通常需要根据不同的条件显示不同的内容。 在 React 中,您可以使用 if 语句、&& 和 ? : 等JavaScript运算符语法有条件地渲染 JSX。
在此示例中,JavaScript && 运算符用于有条件地呈现复选标记:
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>
);
}
准备好学习这个主题了吗?
阅读条件渲染以了解有条件地渲染内容的不同方式。
渲染列表
您通常希望显示数据集合中的多个相似组件。 您可以将 JavaScript 的 filter() 和 map() 与 React 结合使用,以过滤数据数组并将其转换为组件数组。
对于每个数组项,您需要指定一个key。 通常,您会希望使用数据库中的 ID 作为key。 key让 React 跟踪每个项目在列表中的位置,即使列表发生变化。
App.js
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>
);
}
data.js
export const people = [{
id: 0,
name: 'Creola Katherine Johnson',
profession: 'mathematician',
accomplishment: 'spaceflight calculations',
imageId: 'MK3eW3A'
}, {
id: 1,
name: 'Mario José Molina-Pasquel Henríquez',
profession: 'chemist',
accomplishment: 'discovery of Arctic ozone hole',
imageId: 'mynHUSa'
}, {
id: 2,
name: 'Mohammad Abdus Salam',
profession: 'physicist',
accomplishment: 'electromagnetism theory',
imageId: 'bE7W1ji'
}, {
id: 3,
name: 'Percy Lavon Julian',
profession: 'chemist',
accomplishment: 'pioneering cortisone drugs, steroids and birth control pills',
imageId: 'IOjWm71'
}, {
id: 4,
name: 'Subrahmanyan Chandrasekhar',
profession: 'astrophysicist',
accomplishment: 'white dwarf star mass calculations',
imageId: 'lrWQx8l'
}];
utils.js
export function getImageUrl(person) {
return (
'https://i.imgur.com/' +
person.imageId +
's.jpg'
);
}
准备好学习这个主题了吗?
阅读渲染列表以了解如何渲染组件列表以及如何选择key。
保持组件纯净
一些 JavaScript 函数是纯函数。 纯函数:
- 管好自己的事。 它不会更改调用之前存在的任何对象或变量。
- 相同的输入,相同的输出。 给定相同的输入,纯函数应该总是返回相同的结果。
通过严格地将您的组件编写为纯函数,您可以在代码库增长时避免一整类令人困惑的错误和不可预测的行为。 这是一个不纯洁的组件的例子:
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} />
</>
);
}
准备好学习这个主题了吗?
阅读保持组件纯净以了解如何将组件编写为纯粹的、可预测的函数。
网友评论