通过 JSX Control Statements 编写 JSX

通过 JSX Control Statements 编写 JSX

一、前言

一些开发者,特别是有使用过「模板技术」的开发者(例如 Handlebars),刚开始尝试使用 React 编写应用时,可能会惊讶的发现,JSX 竟然没有内建支持类似其它模板引擎似的任何结构控制语句或指令。但这就是 JSX,它就是这么设计的,JSX 不是传统的模板,也不需要某个模板引擎去解析。大体上,可以将 JSX 看成普通 JavaScript 表达式的语法糖。

下边的的代码是一个「普通的 JavaScript 代码示例」

render () {
  return (if(true){
    ...
  }else{
    ...
  });
}

如上代码不合法的,同样,下边的 jsx 代码也是不合法的

render () {
  return (<div>
  {if(true) <span>1</span> else <span>2</span> }
  </div>);
}

因为,JavaScript 不能在一个「表达式」中嵌入「控制语句」。

二、能做什么?

JSX-Control-Statements 为 JSX 增加了基本的结构控制语句,比如条件和循环控制语句。通过将插件将「组件风格」的控制语句最终转换为普通 JS 代码,例如:

<If condition={condition()}>Hello World!</If>

将会转换为

condition() ? 'Hello World!' : null

三、实现原理及说明

这看起来,似乎很容易实现,通过一系列表组件好像就能实现,但事实上这在 React 中这是不可行的,如果用「组件」的方式实现,类似如下代码

<ul>
  <ForComponent each="item" index="index" of={list}>
     <li key={index}>{item.title}</li>
  </ForComponent>
</ul>

组件的方式实现上边的代码,将会抛出来一个错误 Cannot read property 'title' of undefined

因为 React 在执行到 ForComponent 时就是会执行它的 children ,想达到目的,需要延后执行 FormComponent 的 children,那么只能用一个 function 包裹,并在这个函数中返回 jsx 表达式,但这将比直接写 map 方法还麻烦。

所以,JSX Control Statements 是一个 Babel 插件,采取了在「编译阶段」将「控制标签」转换为「普通的 JavaScript 表达式」的方案,最终编译结果和原来的写法没有什么不同。

四、安装

需要先行安装好 Babel,之后通过 npm 安装 jsx-control-statements

npm install --save-dev jsx-control-statements

还需要在 .babelrc 中配置插件,如下

{
  ...
  "plugins": ["jsx-control-statements"]
}

五、核心语法

If 标签

用来表示最简单的条件判断逻辑

// 简单示例
<If condition={ true }>
  <span>IfBlock</span>
</If>

// 包括多个子元素及表达式
<If condition={ true }>
  one { "two" }
  <span>three</span>
  <span>four</span>
</If>

<If>

if 的 body 部分只有在 condition 为 true 才会渲染

属性名 类型 必须
condition boolean

<Else /> (deprecated)

Eles 已废弃,不推荐使用,它会破坏 JSX/XML 的语法,并且影响自动格式化。

转换

If 标签将会预编译为「三元表达式」

// 转换前
<If condition={ test }>
  <span>Truth</span>
</If>

// 转换后
{ test ? <span>Truth</span> : null }

Choose 标签

Choose 是比 If 更复杂分支结构写法

<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>

// default block is optional; minimal example:
<Choose>
  <When condition={true}>
    <span>IfBlock</span>
  </When>
</Choose>

<Choose>

Choose 的子元素只允许出现 WhenOtherwise,其中最少需要有一个 When,而 Otherwise 是可选的

<When>

<If> 类似

属性名 类型 必须
condition boolean

<Otherwise>

没有任何一个 When 满足条件时,将会渲染 Otherwise

转换

Choose 标签同样将会预编译为「三元表达式」

// 转换前
<Choose>
  <When condition={ test1 }>
    <span>IfBlock1</span>
  </When>
  <When condition={ test2 }>
    <span>IfBlock2</span>
  </When>
  <Otherwise>
    <span>ElseBlock</span>
  </Otherwise>
</Choose>

// 转换后
{ test1 ? <span>IfBlock1</span> : test2 ? <span>IfBlock2</span> : <span>ElseBlock</span> }

For 标签

For 的命名用方法,如下

  // 注意,需要指定 key 属性
  <For each="item" of={ this.props.items }>
    <span key={ item.id }>{ item.title }</span>
  </For>

  <For each="item" index="idx" of={ [1,2,3] }>
    <span key={ idx }>{ item }</span>
    <span key={ idx + '_2' }>Static Text</span>
  </For>
属性名 类型 必须 说明
of Array/collection 列表或包含 map 方法的集合
each string 循环「项」变量名
index string 循环「索引」变量名

注意,For 不能作为根元素

转换

// 转换前
<For each="item" index="index" of={ items )}>
  <span key={ item.id }>{ index }. { item.title }</span>
</For>

// 转换前
{
  items.map( function(item, index) {
    <span key={ item.id }>{ index }. { item.title }</span>
  })
}

With 标签

用于将值赋给局部变量

// 简单用法
<With foo={ 47 } bar={ 'test' }>
  <span>{ foo }</span>
  <span>{ bar }</span>
</With>

// 嵌套使用
<With foo={ 47 }>
  <With bar={ 'test' }>
    <span>{ foo }</span>
    <span>{ bar }</span>
  </With>
</With>
属性名 类型 必须 说明
any any 将值赋给指定名称的局部变量

注意,定义的「变量」仅在 With 块中可用。

转换

<With> 将会转换为一个「匿名的立即执行函数」

// 转换前
<With foo={ 47 }>
  <span>{ foo }</span>
</With>

// 转换后
{
  (function(foo) {
    return <span>{ foo }</span>
  }).call(this, 47)
}

六、对比普通 JS/JSX 写法的对比

带来的好处

  • 更直观、对于习惯于模板语法的开发人员或设计人员,更接近于传统模板写法
  • 减少 JS/JSX 相互隔断导致的代码「支离破碎」
  • 更好的可读性和整洁,不过这取决于你的个人喜好。

一点小问题

  • 多了一步编译,会多用一点点构建时间
  • 依赖 Bable 6,并需要配置一下 .babelrc

七、如何进行语法检查?

ESLint

所有结构控制标签都是通过 Babel 插件进行转义的, 不需要 require or import,所有在进行「语法检查」时,将会出现「变量未定义」的警告或错误。

但是,有一个 ESlint 插件可处理这个问题
ESLint plugin for JSX-Control-Statements

-- end --

时间: 2024-08-18 08:17:12

通过 JSX Control Statements 编写 JSX的相关文章

React JSX vs Vue 模板:前端界的一次对决

本文讲的是React JSX vs Vue 模板:前端界的一次对决, React.js 与 Vue.js 是地球上最受欢迎的两个 JavaScript 库.他们都非常强大并且相对容易上手和使用. React 和 Vue 的共同点: 使用虚拟 DOM 提供响应式的视图组件 保持对视图的关注 伴随着如此多的相同点,你可能会怀疑它们就是同一个库的不同版本. 不过这两个库有一个主要的区别:就是他们如何授权给你(开发者)创建你自己的视图组件,甚至是你的应用. React 使用 JSX(由 React 小组

用Jsx写Vue组件

前言 我们平常写vue的组件时,一般都是用的是模版,这种方式看起来比较简洁,而且vue作者也推荐使用这个方式,但是这种方式也有一些它的弊端,例如模版调试麻烦,或者在一些场景下模版描述可能没那么简单和方便. 下面我们要讲的是如何在vue里面写jsx,知道react的人应该都知道jsx,jsx的一个特性就是非常灵活,虽然有的人觉得jsx很丑陋,把逻辑都写到模版的感觉,但萝卜青菜各有所爱,适合自己适合团队的就是最好的. 在使用jsx之前我们需要安装一个babel插件(babel-plugin-tran

JavaScript的React框架中的JSX语法学习入门教程_基础知识

什么是JSX? 在用React写组件的时候,通常会用到JSX语法,粗看上去,像是在Javascript代码里直接写起了XML标签,实质上这只是一个语法糖,每一个XML标签都会被JSX转换工具转换成纯Javascript代码,当然你想直接使用纯Javascript代码写也是可以的,只是利用JSX,组件的结构和组件之间的关系看上去更加清晰. var MyComponent = React.createClass({/*...*/}); var myElement = <MyComponent som

深入理解 JSX

JSX 是一个看起来很像 XML 的 JavaScript 语法扩展.React 可以用来做简单的 JSX 句法转换. 为什么要使用 JSX? 你不需要为了 React 使用 JSX,可以直接使用纯粹的 JS.但我们更建议使用 JSX , 因为它能定义简洁且我们熟知的包含属性的树状结构语法. 对于非专职开发者(比如设计师)同样比较熟悉. XML 有固定的标签开启和闭合.这能让复杂的树更易于阅读,优于方法调用和对象字面量的形式. 它没有修改 JavaScript 语义. HTML标签 与 Reac

SYSMOD简介

本文将着重介绍SMP/E中System Modification,或称为SYSMOD,它是SMP/E安装的对象.而SMP/E是安装z/OS及IBM大型机相关软件产品的重要工具,因此清楚理解SYSMOD对于z/OS及IBM大型机软件的安装有重要意义.本文重点介绍SYSMOD常用的三种类型,并对其中常用字段进行简单介绍. 在z/OS系统中,一个可执行程序由Module,Macro,Hold Data等元素组成,并通过Packaging功能将所有元素打包成一个可用于安装和维护的产品.而SMP/E就是专

有感 Visual Studio 2015 RTM 简介 - 八年后回归 Dot Net,终于迎来了 Mvc 时代,盼走了 Web 窗体时代

有感 Visual Studio 2015 RTM 简介 - 八年后回归 Dot Net,终于迎来了 Mvc 时代,盼走了 Web 窗体时代 太阳火神的美丽人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商业用途-保持一致"创作公用协议 转载请保留此句:太阳火神的美丽人生 -  本博客专注于 敏捷开发及移动和物联设备研究:iOS.Android.Html5.Arduino.pcDuino,否则,出自本博客的文章拒绝转载或再转载,谢谢合作. 关于

Jason Miller: Preact: Into the void 0(译)

title: Preact:Into the void 0(译) date: 2017-09-04 19:00:00 tags: [Preact, JSX, 虚拟DOM, 性能] 本文整理自Jason Miller在JSConf上的talk.原视频地址: https://www.youtube.com/watch?v=LY6y3HbDVmg 开场白 嗨,大家好,我是Jason,Github上那个developit和推特上的_developit,是一系列库的作者(serial library au

2016年里做前端是怎样一种体验

问:最近我接手了一个新的Web项目,不过老实说我已经好久没碰过这方面的代码了.听说前端的技术栈已经发生了极大的变革,不知道你现在是不是仍然处于最前沿的开发者阵列?   答:准确来说,过去俗称的写网页的,现在应该叫做Front End Engineer,我确实属于这所谓的前端工程师.并且我才从JSConf与ReactConf面基回来,因此我觉得我觉得我还是了解目前Web前端领域最新的面貌的.     问:不错不错,我的需求其实也不复杂,就是从后端提供的REST风格的EndPoint来获取用户活动数

Matlab编程基础

原文:Matlab编程基础   平台:Win7 64 bit,Matlab R2014a(8.3)   "Matlab"是"Matrix Laboratory" 的缩写,中文"矩阵实验室",是强大的数学工具.本文侧重于Matlab的编程语言侧面,讲述Matlab的基本语法,以及用Matlab语言进行程序设计.值得一提的是,Matlab从R2014a版本开始支持中文语言了!   1.基本概念 Matlab默认启动后界面: Matlab有关的文件后缀