如何在 react 中使用 if-elseif-else 多重条件判断
使用过 Vue 的同学们都知道,在 Vue 中有v-if
, v-elseif
和v-else
的语法糖,方便我们进行流程控制。但 react 中使用的 jsx,并没有这些语法糖,而是使用一些其他方式来实现条件控制的。
1. react 中的条件渲染 #
在 react 中有多种实现条件渲染的方式,我们每个稍微介绍一下。
1.1 与运算符&& #
当前面的表达式为真时,则执行后面的表达式。相当于if
。
// 当showModal变量为真时,则渲染弹窗,否则不显示
{showModal && <Modal>Modal>}
这里需要注意的是,当使用长度来控制的时候,要使用判断表达式,而不是直接用.length
来判断,
// 要判断length>0,若只用list.length判断时,最后会渲染出来一个0
{list.length > 0 && <Modal>Modal>}
1.2 三目运算 #
当需要非黑即白
时,这里就用到了三目运算。相当于if-else
:
{list.length>0 ? `您一共有${list..length}条数据` : '您暂时还没有数据'}
1.3 立即执行或者单独的方法渲染 #
当需要更复杂的判断时,例如 3 个及以上的情况,或者多个判断条件时,即if-elseif-else
的类型时,情况就稍微复杂一些。不过我们依然也有多种方式来实现。
- 多个嵌套的三目运算;
- 立即执行方法;
- 单独的方法;
1.3.1 多个嵌套的三目运算 #
嵌套的三目运算,也能作为多个 if 判断,但看起来实现逻辑有点乱:
const Home = () => {
return <div>{A ? <>a right> : B ? <>b right> : <>else>}
;
};
1.3.2 立即执行 #
const Home = () => {
return (<div>
{
(() => {
if (A) {
return <>a right>
}
if (B) {
return <>b right>
}
return <>else>
})();
}
);
}
1.3.3 单独的方法 #
const Home = () => {
const projectStatus = 1;
const renderItem = (item) => {
if (projectStatus !== 1) {
return <button>活动暂未开始或已结束button>;
}
if (item.status === 1) {
return <button>点击参与button>;
}
return <button>已无库存button>;
};
return <div>{list.map((item) => renderItem(item))}div>;
};
立即执行方法和单独的方法,都把判断逻辑进行了割裂。如果我依然想在 render 中的 jsx 中,写判断怎么办呢?
2. 新的方式 #
这里我一直想着用 Vue 中的方式一样,无需将条件判断独立出来,而是直接在顺着整体的思路往下写。这里我就封装了一个if-elseif-else
的组件。
2.1 调用方式 #
先看下使用方式,然后再看代码实现。
import { When, Case } from './when';
const Home = () => {
return (
<div className="btn-container">
<When>
<Case if={status === 0 || status === 2}>
<Button className="donate-btn-common cant-donate-hotvalue">
{status === 0 ? '活动还未开始' : '活动已结束'}
Button>
Case>
<Case elseif={projectState.process >= 100}>
<Button className="donate-btn-common cant-donate-hotvalue">该项目已捐满Button>
Case>
<Case else>
<Button loading={btnLoading} className="donate-btn-common donate-hotvalue" onClick={handleDonateClick}>
捐热力值帮助TA
Button>
Case>
When>
div>
);
};
这里用When
进行包装,然后每个Case
对应 1 个判断条件,从上往下,若某个为真,则直接渲染 children 中的内容,否则接着往下判断,直到最后。
这样实现起来,流程也比较顺,然后条件判断也很清晰。
2.2 代码实现 #
我们在这里直接贴代码,看看是怎么实现的:
import React from 'react';
const isArray = (arg: any): boolean => {
if (Array.isArray) {
return Array.isArray(arg);
}
return Object.prototype.toString.call(arg) === '[object Array]';
};
interface CaseProps {
if?: boolean;
elseif?: boolean;
else?: boolean;
children: JSX.Element | JSX.Element[];
}
export const Case = (props: CaseProps) => {
return <>{props.children}>;
};
export const When = ({ children }: { children: any }): JSX.Element | null => {
if (!children) {
return null;
}
let schildren: any = [];
if (isArray(children)) {
// 当存在多个case节点时,children为数组
schildren = children;
} else {
// 当只有一个case节点,children为object类型
schildren.push(children);
}
// 判断所有的子节点是不是Case类型
schildren.forEach((child: any) => {
if (!child.type || child.type.name !== Case.name) {
throw new Error('the children of component When muse be component Case');
}
});
// 查找if的节点,若有则直接返回
const ifChildren = schildren.filter((item: any) => item.props.if);
if (ifChildren.length) {
return <>{ifChildren}>;
}
// 再查找elseif的节点
const elseIfChildren = schildren.filter((item: any) => item.props.elseif);
if (elseIfChildren.length) {
// 这里只输出第1个为true的组件
return <>{elseIfChildren[0]}>;
}
// 返回其他的节点
return <>{schildren.filter((item: any) => item.props.else)}>;
};
最终实现起来也非常的简单,按照顺序查找相应的属性,然后进行返回即可。
3. 总结 #
在 react 中,条件判断的方式有很多,官方的文档就介绍了很多种,但要实现一些稍微复杂点的条件判断时,就会让代码显得很凌乱。这里我也就实现实现了一套多重判断的机制。
评论