React 的组件逻辑是运行时执行的,因此,我们可以在 React 组件中加入条件判断的逻辑,根据不同的条件,返回不同的 JSX,以渲染不同的内容。
React 组件可以支持所有的 JavaScript 条件判断的逻辑,常用的有:
&&
运算符 和 ||
运算符? :
接下来,我们以一个列表清单组件为例,来演示如何使用条件判断的逻辑。
我们要实现一个清单列表的功能,支持展示清单的名称、是否选中、是否删除。如果是选中和删除,会有不同的 UI 样式。
实现的案例效果如下所示:
根据需求,我们可以封装一个 Item 组件来展示每一条清单项。并且需要传入清单的名称、是否选中、是否删除三个属性以供组件内部使用。
1interface InventoryItemProps {2name: string,3isChecked: boolean,4isDelete: boolean,5}67export default function InventoryItem({ name, isChecked, isDelete }: InventoryItemProps) {8...9}
然后我们考虑前面的选中图标,如果选中,则显示一个对号,否则显示一个方框。此时就非常适合使用条件判断来实现,这里我们使用三元运算符
1const icon = isChecked ? <SquareCheckBig className="w-5 h-5 text-green-600 dark:text-green-400" />2: <Square className="w-5 h-5 text-gray-400 dark:text-gray-500" />
当然,也可以使用 if 语句来实现,但是三元运算符更加简洁。
1let icon = null2if (isChecked) {3icon = <SquareCheckBig className="w-5 h-5 text-green-600 dark:text-green-400" />4} else {5icon = <Square className="w-5 h-5 text-gray-400 dark:text-gray-500" />6}
除此之外,我们注意到,状态不同,UI 的样式也不一样,因此,在 className 上,我们也需要使用条件判断来设置不同的样式。
完整的实现逻辑如下所示
10import {Square, SquareCheckBig} from 'lucide-react'2030interface InventoryItemProps {40name: string,50isChecked: boolean,60isDelete: boolean,70}8090export default function InventoryItem({ name, isChecked, isDelete }: InventoryItemProps) {10const icon = isChecked ? <SquareCheckBig className="w-5 h-5 text-green-600 dark:text-green-400" />11: <Square className="w-5 h-5 text-gray-400 dark:text-gray-500" />1213return (14<div className={`15flex items-center gap-3 p-4 rounded-lg border transition-all duration-20016${isChecked17? 'bg-green-50 border-green-200 dark:bg-green-950/20 dark:border-green-800'18: 'bg-white border-gray-200 dark:bg-gray-800 dark:border-gray-700'19}20${isDelete ? 'opacity-50' : 'opacity-100'}21`}>22<div className="flex-shrink-0">23{icon}24</div>25<span className={`26flex-1 text-sm font-medium27${isDelete28? 'text-green-800 dark:text-green-200 line-through'29: 'text-gray-900 dark:text-gray-100'30}31`}>32{name}33</span>34</div>35)36}
根据个人习惯的不同。有的时候,我们更习惯于把复杂的条件判断逻辑从 JSX 中单独抽离出来,以确保 JSX 的简洁与可读性。除此之外,过多的代码使用三木运算也会导致可读性的下降。
这只是个人习惯的侧重,并不是必须的
此时,我们可以使用 clsx 库来优化代码的可读性。重新调整之后,完整的代码如下所示
10import {Square, SquareCheckBig} from 'lucide-react'20import clsx from 'clsx'3040export default function InventoryItem({ name, isChecked, isDelete }: InventoryItemProps) {50const cls = clsx(60'flex items-center gap-3 p-4 rounded-lg border transition-all duration-200',70{80'bg-green-50 border-green-200 dark:bg-green-950/20 dark:border-green-800': isChecked,90'bg-white border-gray-200 dark:bg-gray-800 dark:border-gray-700': !isChecked,10'opacity-50': isDelete,11'opacity-100': !isDelete12}13)1415const spanCls = clsx(16'flex-1 text-sm font-medium',17{18'text-green-800 dark:text-green-200 line-through': isDelete,19'text-gray-900 dark:text-gray-100': !isDelete20}21)2223return (24<div className={cls}>25<div className="flex-shrink-0">26{isChecked ? <SquareCheckBig className="w-5 h-5 text-green-600 dark:text-green-400" /> : <Square className="w-5 h-5 text-gray-400 dark:text-gray-500" />}27</div>28<span className={spanCls}>29{name}30</span>31</div>32)33}3435interface InventoryItemProps {36name: string,37isChecked: boolean,38isDelete: boolean,39}
在 React 中,我们可以使用一切 JavaScript 支持的条件判断,这为 React 组件提供了强大的灵活性支撑。看了完整的案例之后,这里我们再做一个简单的演示。
1if (condition) {2// do something3return <div>do something</div>4} else {5// do something6return <div>do something</div>7}
1// 三元运算符2return condition ? <div>do something</div> : <div>do something</div>
1// 范围也可以缩小一点2return <div>{condition ? 'do something' : 'do something'}</div>
1// 使用 && 运算符2return <div>{condition && <div>do something</div>}</div>
1// 使用 || 运算符2return <div>{condition || <div>do something</div>}</div>