登录 主页

React Conditional Rendering

2024-06-18 03:43PM

参考:https://react.dev/learn/conditional-rendering

你的组件通常需要根据不同的条件显示不同的内容。在React中,您可以使用JavaScript语法来条件性地渲染JSX,例如使用 if 语句、&& 和 ?: 运算符。

1.有条件地返回JSX

假设您有一个名为 PackingList 的组件,它渲染了多个 Items,这些 Items 可以被标记为已打包(packed)或未打包(not packed)

// src/pages/PackingList.js

import React from 'react';

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

export default function PackingList() {
  return (
    <section>
      <h1>Sally Ride Packing List</h1>
      <ul>
        <Item
          isPacked={true}
          name="Space suit"
        />
        <Item
          isPacked={true}
          name="Helmet with a golden leaf"
        />
        <Item
          isPacked={true}
          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。有了这个改变,一些项目在末尾会得到一个勾号(✔)。

// src/pages/PackingListIf.js

import React from 'react';

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

export default function PackingListIf() {
  return (
    <section>
      <h1>Sally Ride 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来处理的

2.有条件地不返回任何内容null

在某些情况下,你可能根本不想渲染任何内容,例如:假设你根本不想显示打包的项目,组件必须返回某些东西。在这种情况下,你可以返回null:

if (isPacked) {

return null;

}

return <li className="item">{name}</li>;

如果isPacked是真的,组件将返回空,即null。否则,它将返回用于渲染的JSX

// src/pages/PackingListNull.js

import React from 'react';

function Item({name, isPacked}) {
  if (isPacked) {
    return null;
  }
  return <li className="item">{name}</li>
}

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

页面显示内容如下:

在实践中,从组件返回null并不常见,因为这可能会让尝试渲染它的开发者感到惊讶。更常见的做法是在父组件的JSX中条件性地包含或排除该组件。以下是如何做到这一点的方法:

1)有条件地包含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(Don't Repeat Yourself,即不要重复自己)原则

2)条件(三元)运算符 ( ? :) 

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”

现在假设您想要将已完成项的文本包装进另一个 HTML 标签中,比如使用 `<del>` 来划掉它。您可以添加更多的换行和括号,以便在每种情况中更容易地嵌套更多的 JSX。 、、

// src/pages/PackingListTernary.js

import React from 'react';
function Item({name, isPacked}) {
  return (
    <li className="item">
      {isPacked ? (
        <del>
          {name + ' ✔'}
        </del>
      ) : (
        name
      )}
    </li>
  );
}
export default function PackingListTernary() {
  return (
    <section>
      <h1>Sally Ride 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中,标记是你代码的一部分,因此你可以使用变量和函数等工具来整理复杂的表达式。

3)逻辑与运算符(&&)

你将遇到的另一个常见快捷方式是JavaScript逻辑与(&&)运算符。在React组件,内部,当你想要在条件为true时渲染一些JSX,条件为false时不渲染任何内容时,它经常出现,使用&&,你可以在isPacked为true时仅条件性地渲染'✔'

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

可以这样理解:如果isPacked为true,那么(&&)渲染'✔',反之则不渲染任何内容

下面是它的实际应用示例:

// src/pages/PackingListLogical.js

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

export default function PackingListLogical() {
  return (
    <section>
      <h1>Sally Ride 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一样,不会在其位置渲染任何内容。

注意:不要将数字放在&&的左侧

测试条件时,JavaScript会自动将左侧转换为布尔值(boolean)。然而,如果左侧是0,那么整个表达式得到该值(0),React将会渲染0而不是什么都不渲染。

例如,一个常见的错误是编写像messageCount && <p>New messages</p>这样的代码,人们很容易假设当messageCount为0时它为什么也不渲染,但实际上它渲染了0本身。

要修复这个问题,使左侧成为布尔值: messageCount > 0 && <p>New messages</p>

返回>>

登录

请登录后再发表评论。

评论列表:

目前还没有人发表评论