你的组件经常需要根据不同的条件显示不同的内容。在 React 中,你可以使用 JavaScript 语法(例如 if 语句、&& 和 ? : 运算符)有条件地渲染 JSX。
你将学习
- 如何根据条件返回不同的 JSX
- 如何有条件地包含或排除 JSX 代码段
- 在 React 代码库中会遇到的常见条件语法快捷方式
有条件地返回 JSX
假设你有一个 PackingList 组件,它渲染多个 Item,这些项目可以标记为已打包或未打包。
function Item({ name, isPacked }) { return <li className="item">{name}</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> ); }
注意,一些 Item 组件的 isPacked 属性设置为 true 而不是 false。如果 isPacked={true},你想为已打包的项目添加一个复选标记 (✅)。
你可以将其编写为 if/else 语句,如下所示
if (isPacked) {
return <li className="item">{name} ✅</li>;
}
return <li className="item">{name}</li>;如果 isPacked 属性为 true,这段代码将返回不同的 JSX 树。 通过此更改,某些项目末尾会显示复选标记。
function Item({ name, isPacked }) { if (isPacked) { return <li className="item">{name} ✅</li>; } return <li className="item">{name}</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 的 if 和 return 语句创建分支逻辑。在 React 中,控制流(如条件)由 JavaScript 处理。
使用 null 有条件地返回空
在某些情况下,你根本不想渲染任何内容。例如,假设你根本不想显示已打包的项目。组件必须返回某些内容。在这种情况下,你可以返回 null
if (isPacked) {
return null;
}
return <li className="item">{name}</li>;如果 isPacked 为 true,则组件将不返回任何内容,即 null。否则,它将返回要渲染的 JSX。
function Item({ name, isPacked }) { if (isPacked) { return null; } return <li className="item">{name}</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> ); }
实际上,从组件返回 null 并不常见,因为它可能会让尝试渲染它的开发者感到意外。更常见的是,你将在父组件的 JSX 中有条件地包含或排除该组件。以下是操作方法!
有条件地包含 JSX
在前面的示例中,你控制了组件将返回哪个(如果有!)JSX 树。你可能已经注意到渲染输出中有一些重复。
<li className="item">{name} ✅</li>非常类似于
<li className="item">{name}</li>两个条件分支都返回 <li className="item">...</li>
if (isPacked) {
return <li className="item">{name} ✅</li>;
}
return <li className="item">{name}</li>;虽然这种重复并不有害,但它可能会使你的代码更难维护。如果你想更改 className 该怎么办?你必须在代码中的两个地方进行更改!在这种情况下,你可以有条件地包含少量 JSX,以使你的代码更 DRY。
条件(三元)运算符 (? :)
JavaScript 有一种简洁的语法来编写条件表达式——条件运算符 或“三元运算符”。
不是这样
if (isPacked) {
return <li className="item">{name} ✅</li>;
}
return <li className="item">{name}</li>;你可以这样写
return (
<li className="item">
{isPacked ? name + ' ✅' : name}
</li>
);你可以把它理解为“如果 isPacked 为真,则 (?) 渲染 name + ' ✅',否则 (:) 渲染 name”。
深入探讨
如果您来自面向对象的编程背景,您可能会认为上面这两个例子细微不同,因为其中一个可能会创建两个不同的<li>“实例”。但是 JSX 元素不是“实例”,因为它们不保存任何内部状态,也不是真正的 DOM 节点。它们是轻量级的描述,就像蓝图一样。因此,这两个例子实际上是完全等价的。保持和重置状态详细介绍了其工作原理。
现在假设您想将已完成项目的文本包装到另一个 HTML 标签中,例如<del> 来将其删除线。您可以添加更多换行符和括号,以便更容易地将更多 JSX 嵌套到每种情况下。
function Item({ name, isPacked }) { return ( <li className="item"> {isPacked ? ( <del> {name + ' ✅'} </del> ) : ( name )} </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> ); }
这种样式适用于简单的条件,但要适度使用。如果您的组件嵌套了过多的条件标记而变得混乱,请考虑提取子组件以清理代码。在 React 中,标记是代码的一部分,因此您可以使用变量和函数等工具来整理复杂的表达式。
逻辑与运算符 (&&)
您还会遇到另一个常见的快捷方式,即JavaScript 逻辑与 (&&) 运算符。在 React 组件内部,当您想要在条件为真时渲染一些 JSX,或者否则不渲染任何内容时,它经常出现。使用&&,您可以有条件地仅在isPacked 为 true 时渲染复选标记。
return (
<li className="item">
{name} {isPacked && '✅'}
</li>
);您可以把它理解为“如果 isPacked,则 (&&) 渲染复选标记,否则不渲染任何内容”。
以下是实际操作
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 && 表达式如果左侧(我们的条件)为true,则返回其右侧的值(在本例中为复选标记)。但是,如果条件为false,则整个表达式将变为false。React 将false视为 JSX 树中的“空洞”,就像null或undefined一样,并且不会在其位置渲染任何内容。
有条件地将 JSX 分配给变量
当快捷方式妨碍编写简洁代码时,尝试使用if语句和变量。可以使用let重新赋值已定义的变量,因此首先提供要显示的默认内容,即名称
let itemContent = name;使用if语句,如果isPacked为true,则将JSX表达式重新赋值给itemContent
if (isPacked) {
itemContent = name + " ✅";
}花括号打开了“通向JavaScript的窗口”。 在返回的JSX树中使用花括号嵌入变量,将先前计算的表达式嵌套在JSX内部
<li className="item">
{itemContent}
</li>这种风格最为冗长,但也最灵活。以下是它的实际应用
function Item({ name, isPacked }) { let itemContent = name; if (isPacked) { itemContent = name + " ✅"; } return ( <li className="item"> {itemContent} </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> ); }
像之前一样,这不仅适用于文本,也适用于任意的JSX
function Item({ name, isPacked }) { let itemContent = name; if (isPacked) { itemContent = ( <del> {name + " ✅"} </del> ); } return ( <li className="item"> {itemContent} </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,这些不同的风格一开始可能会显得难以掌握。但是,学习它们将有助于您阅读和编写任何JavaScript代码——而不仅仅是React组件!首先选择您喜欢的风格,如果您忘记了其他风格的工作方式,可以再次参考本文。
回顾
- 在React中,您可以使用JavaScript控制分支逻辑。
- 您可以使用
if语句有条件地返回JSX表达式。 - 您可以有条件地将一些JSX保存到变量中,然后使用花括号将其包含在其他JSX中。
- 在JSX中,
{cond ? <A /> : <B />}表示“如果cond为真,则渲染<A />,否则渲染<B />”。 - 在JSX中,
{cond && <A />}表示“如果cond为真,则渲染<A />,否则不渲染任何内容”。 - 这些快捷方式很常见,但如果您更喜欢使用普通的
if,则不必使用它们。
挑战 1的 3: 使用? :显示未完成项目的图标
如果isPacked不是true,则使用条件运算符(cond ? a : b)渲染一个❌。
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> ); }