如何在 react 中使用 if-elseif-else 多重条件判断

蚊子前端博客
发布于 2020-08-28 14:09
react中通常使用与运算符和三目运算进行条件判断,但遇到更复杂的条件判断时,就相对来说比较麻烦一些,这种情况应该怎么处理呢?

使用过 Vue 的同学们都知道,在 Vue 中有v-if, v-elseifv-else的语法糖,方便我们进行流程控制。但 react 中使用的 jsx,并没有这些语法糖,而是使用一些其他方式来实现条件控制的。

1. react 中的条件渲染

在 react 中有多种实现条件渲染的方式,我们每个稍微介绍一下。

1.1 与运算符&&

当前面的表达式为真时,则执行后面的表达式。相当于if

COPYJAVASCRIPT

// 当showModal变量为真时,则渲染弹窗,否则不显示 <div>{showModal && <Modal></Modal>}</div>

这里需要注意的是,当使用长度来控制的时候,要使用判断表达式,而不是直接用.length来判断,

COPYJAVASCRIPT

// 要判断length>0,若只用list.length判断时,最后会渲染出来一个0 <div>{list.length > 0 && <Modal></Modal>}</div>

1.2 三目运算

当需要非黑即白时,这里就用到了三目运算。相当于if-else

COPYJAVASCRIPT

<div> {list.length>0 ? `您一共有${list..length}条数据` : '您暂时还没有数据'} </div>

1.3 立即执行或者单独的方法渲染

当需要更复杂的判断时,例如 3 个及以上的情况,或者多个判断条件时,即if-elseif-else的类型时,情况就稍微复杂一些。不过我们依然也有多种方式来实现。

  1. 多个嵌套的三目运算;

  2. 立即执行方法;

  3. 单独的方法;

1.3.1 多个嵌套的三目运算

嵌套的三目运算,也能作为多个 if 判断,但看起来实现逻辑有点乱:

COPYJAVASCRIPT

const Home = () => { return <div>{A ? <>a right</> : B ? <>b right</> : <>else</>}</div>; };

1.3.2 立即执行

COPYJAVASCRIPT

const Home = () => { return (<div> { (() => { if (A) { return <>a right</> } if (B) { return <>b right</> } return <>else</> })(); } </div>); }

1.3.3 单独的方法

COPYJAVASCRIPT

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 调用方式

先看下使用方式,然后再看代码实现。

COPYJAVASCRIPT

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 代码实现

我们在这里直接贴代码,看看是怎么实现的:

COPYJAVASCRIPT

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 中,条件判断的方式有很多,官方的文档就介绍了很多种,但要实现一些稍微复杂点的条件判断时,就会让代码显得很凌乱。这里我也就实现实现了一套多重判断的机制。

机制如我-蚊子的前端博客

标签:
阅读(1773) 评论(8)

公众号:

qrcode

微信公众号:前端小茶馆