Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

React JSX 中的条件判断 #40

Open
hjzheng opened this issue Jun 10, 2017 · 1 comment
Open

React JSX 中的条件判断 #40

hjzheng opened this issue Jun 10, 2017 · 1 comment
Labels

Comments

@hjzheng
Copy link
Member

hjzheng commented Jun 10, 2017

在书写 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>
@hjzheng hjzheng added the React label Jun 10, 2017
@kuitos
Copy link

kuitos commented Jun 21, 2017

先赞一个,想法非常好👍
不过 jsx 的拥趸们估计要坐不住了:
『什么竟然说 JSX 不如模板语法?!!』
『你这跟写模板有什么区别,JSX 才是正道,你这个异教徒!』
『这么写简直是在开倒车!!』
哈哈哈哈(逃

@hjzheng hjzheng added ES6 and removed ES6 labels Nov 12, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants