条件渲染:if 语句、三元运算符与逻辑与运算符
在实际应用中,你的组件经常需要根据不同的条件显示不同的内容。例如:
- 如果用户已登录,显示用户头像和“退出”按钮;如果未登录,显示“登录/注册”按钮;
- 如果待办事项已完成,在文字上画一条删除线并在旁边打上勾(✔);
- 如果列表数据为空,显示“暂无数据”的空白占位提示。
在 React 中,没有任何特殊的模板指令(比如 Vue 的 v-if 或 Angular 的 *ngIf)。在 React 里,你使用的就是最纯粹、最自然的 JavaScript 原生逻辑控制语句。
1. 方式一:使用原生的 if/else 语句分支返回
最直接的方式是使用 JavaScript 的 if 语句。根据传入的 prop,直接返回不同的完整 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>行李打包清单</h1>
<ul>
<Item isPacked={true} name="宇航服" />
<Item isPacked={true} name="带金箔的头盔" />
<Item isPacked={false} name="全家福照片" />
</ul>
</section>
);
}
如果 isPacked 是 true,函数在第一个 return 就提前返回带有对勾的标签;如果是 false,则流向第二个 return。
2. 方式二:使用 null 选择性地隐藏组件
有时在某些特定条件下,你希望组件什么都不要渲染(完全隐藏该元素)。
在 React 中,如果一个组件返回 null,React 就不会向页面输出任何 DOM 节点:
function Item({ name, isPacked }) {
if (isPacked) {
// 已经打包好了,不在清单中显示
return null;
}
return <li className="item">{name}</li>;
}
现在,所有 isPacked={true} 的项都会在屏幕上彻底隐形。
3. 方式三:三元运算符(? :)
上面第一种方式虽然直观,但如果你仔细看,<li className="item"> 这个外层标签在两个 return 里被重复写了两遍。随着结构变大,重复写两遍模板会非常冗余。
我们可以使用 JavaScript 的 三元运算符(Ternary Operator,条件 ? 成立时的值 : 不成立时的值),直接把判断内联写在标签中间:
function Item({ name, isPacked }) {
return (
<li className="item">
{isPacked ? name + ' ✔' : name}
</li>
);
}
甚至可以根据条件返回不同的完整 JSX 子标签:
function Item({ name, isPacked }) {
return (
<li className="item">
{isPacked ? (
<del>{name + ' ✔'}</del>
) : (
name
)}
</li>
);
}
(注:<del> 是原生 HTML 标签,表示带有删除线的内容)。
4. 方式四:逻辑与运算符(&&)
在开发中,有一种非常普遍的场景:“如果条件为真,我就渲染这个标记;如果为假,我就什么都不渲染”。
使用三元运算符写成 isPacked ? (<del>...</del>) : null 虽然可以,但末尾带一个 : null 稍显啰嗦。此时可以使用更紧凑的 逻辑与运算符 &&:
function Item({ name, isPacked }) {
return (
<li className="item">
{name} {isPacked && '✔'}
</li>
);
}
原理解析: 在 JavaScript 中,
true && 表达式永远返回右侧表达式的值;而false && 表达式永远返回false。 在 React 中,布尔值false、true、null和undefined在 JSX 中都不会被渲染到页面上。因此,当isPacked为false时,对勾完全不会出现。
5. 高危避坑:切勿把数字 0 放在 && 的左侧!
这是许多初学者甚至资深工程师都踩过的经典大坑:
// ❌ 危险写法!
function Notification({ messageCount }) {
return (
<div>
{messageCount && <p>你有未读消息!</p>}
</div>
);
}
为什么会出 Bug?
当 messageCount === 0 时:
在 JavaScript 中,0 && <p>...</p> 的求值结果不是 false,而是数字 0 本身!
而在 React 中,布尔值不会被渲染,但数字 0 是一个合法的可显示内容!
结果就是:当没有未读消息时,页面上居然孤零零地显示出了一个 数字 “0”!
正确的解决方案
永远确保 && 左侧是一个真正的布尔值(true 或 false):
// ✅ 正确做法一:显式比较大小
{messageCount > 0 && <p>你有未读消息!</p>}
// ✅ 正确做法二:显式转换为布尔类型
{Boolean(messageCount) && <p>你有未读消息!</p>}
// ✅ 正确做法三:使用三元表达式
{messageCount > 0 ? <p>你有未读消息!</p> : null}
总结
- 在 React 中,使用原生 JavaScript 控制流实现条件渲染;
if语句适合根据条件分支提前返回全新的界面结构;- 返回
null可以彻底隐藏组件,不输出任何 DOM; - 三元运算符
? :适合紧凑的双分支切换; - 逻辑与
&&适合“存在才显示”的单向渲染,但务必确保左侧是布尔值,防止数字0泄漏到页面上。