React JSX 中的条件判断
hjzheng opened this issue · comments
在书写 JSX 时,经常会有一类需求,就是在特定条件下 render 一些组件。
例如:
- 显示警告信息时
{this.showMessage && <Message type={'warning'} />}
- 加载表格数据时
{this.loading ? <Loading /> : <Table />}
这里,我使用 JavaScript 表达式进行处理,这样做,从代码的可读性和可维护性上看起来都还不错。
继续增加复杂度
{ show && (isAdmin || hasPermission) && <Dialog /> }
继续增加复杂度
{ isShow && configDataIsDone && (isAdmin || hasPermission) && <Dialog /> }
显而易见,随着复杂度的增加,代码的可读性变的很差,可维护性也变的不好。
此时,最简单的处理方式,创建一个 helper 函数
canShowDialog () {
const { isShow, configDataIsDone, isAdmin, hasPermission } = this.props;
return isShow && configDataIsDone && (isAdmin || hasPermission);
}
... ...
{ this.canShowDialog() && <Dialog /> }
或者创建一个 getter
get canShowDialog () {
const { isShow, configDataIsDone, isAdmin, hasPermission } = this.props;
return isShow && configDataIsDone && (isAdmin || hasPermission);
}
... ...
{ this.canShowDialog && <Dialog /> }
当然,有些时候,也可以依赖一些第三方库
例如 render-if
const { isShow, configDataIsDone, isAdmin, hasPermission } = this.props;
const canShowDialog = renderIf(isShow && configDataIsDone && (isAdmin || hasPermission));
... ...
{ this.canShowDialog(<Dialog />) }
还可以使用高阶组件
react-only-if
const { isShow, configDataIsDone, isAdmin, hasPermission } = this.props;
const DialogOnlyIf = onlyIf(({isShow, configDataIsDone, isAdmin, hasPermission}) => {
return isShow && configDataIsDone && (isAdmin || hasPermission);
})(<Dialog />);
... ...
{ <DialogOnlyIf isShow={...} configDataIsDone={...} isAdmin={...} hasPermission={...} /> }
即使这样,可读性上还是稍差点,不可否认通用编程语言在功能上,远大于模板,毕竟模板只是 DSL,针对特定领域的语言,在某些点上的能力毕竟有限,因为它是针对特定领域的,所以在特定领域的可读性和易用上要好于通用编程语言。
想象一下, 我们可不可以增加一些条件组件,参考一下 AngularJS1.x:
例如:
<div ng-if=“true”>要显示内容</div>
将组件设计成这样:
<If condition={isShow && configDataIsDone && (isAdmin || hasPermission)}>
<Dialog />
</If>
其他组件 参考 ng-switch (else 和 else If 可以用 switch 代替)
<If condition={...}>
{'if语句'}
</If>
<Switch>
<When condition={...}>...</When>
<When condition={...}>...</When>
<Default>....</Default>
</Switch>
庆幸的是,有第三方的库可以进行支持,目前我所知道的有两个库:
react-if
jsx-control-statements
以 jsx-control-statements 为例:
{/* if语句 */}
<If condition={ test }>
<span>Truth</span>
</If>
{/* switch 语句 */}
<Choose>
<When condition={ test1 }>
<span>IfBlock</span>
</When>
<When condition={ test2 }>
<span>ElseIfBlock</span>
<span>Another ElseIfBlock</span>
<span>...</span>
</When>
<Otherwise>
<span>ElseBlock</span>
</Otherwise>
</Choose>
{/* for 循环 */}
<For each="item" index="idx" of={ [1,2,3] }>
<span key={ idx }>{ item }</span>
<span key={ idx + '_2' }>Static Text</span>
</For>
先赞一个,想法非常好👍
不过 jsx 的拥趸们估计要坐不住了:
『什么竟然说 JSX 不如模板语法?!!』
『你这跟写模板有什么区别,JSX 才是正道,你这个异教徒!』
『这么写简直是在开倒车!!』
哈哈哈哈(逃