本文共 3162 字,大约阅读时间需要 10 分钟。
一些开发者,特别是有使用过「模板技术」的开发者(例如 Handlebars),刚开始尝试使用 React 编写应用时,可能会惊讶的发现,JSX 竟然没有内建支持类似其它模板引擎似的任何结构控制语句或指令。但这就是 JSX,它就是这么设计的,JSX 不是传统的模板,也不需要某个模板引擎去解析。大体上,可以将 JSX 看成普通 JavaScript 表达式的语法糖。
下边的的代码是一个「普通的 JavaScript 代码示例」
render () { return (if(true){ ... }else{ ... });}
如上代码不合法的,同样,下边的 jsx 代码也是不合法的
render () { return ({if(true) 1 else 2 });}
因为,JavaScript 不能在一个「表达式」中嵌入「控制语句」。
JSX-Control-Statements 为 JSX 增加了基本的结构控制语句,比如条件和循环控制语句。通过将插件将「组件风格」的控制语句最终转换为普通 JS 代码,例如:
Hello World!
将会转换为
condition() ? 'Hello World!' : null
这看起来,似乎很容易实现,通过一系列表组件好像就能实现,但事实上这在 React 中这是不可行的,如果用「组件」的方式实现,类似如下代码
组件的方式实现上边的代码,将会抛出来一个错误 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"]}
用来表示最简单的条件判断逻辑
// 简单示例IfBlock // 包括多个子元素及表达式one { "two" } three four
if 的 body 部分只有在 condition 为 true 才会渲染
属性名 | 类型 | 必须 |
---|---|---|
condition | boolean | 是 |
Eles 已废弃,不推荐使用,它会破坏 JSX/XML 的语法,并且影响自动格式化。
If 标签将会预编译为「三元表达式」
// 转换前Truth // 转换后{ test ? Truth : null }
Choose 是比 If 更复杂分支结构写法
// default block is optional; minimal example: IfBlock ElseIfBlock Another ElseIfBlock ... ElseBlock IfBlock
Choose 的子元素只允许出现 When
和 Otherwise
,其中最少需要有一个 When
,而 Otherwise
是可选的
和 <If>
类似
属性名 | 类型 | 必须 |
---|---|---|
condition | boolean | 是 |
没有任何一个 When
满足条件时,将会渲染 Otherwise
Choose 标签同样将会预编译为「三元表达式」
// 转换前// 转换后{ test1 ? IfBlock1 : test2 ? IfBlock2 : ElseBlock } IfBlock1 IfBlock2 ElseBlock
For
的命名用方法,如下
// 注意,需要指定 key 属性{ item.title } { item } Static Text
属性名 | 类型 | 必须 | 说明 |
---|---|---|---|
of | Array/collection | 是 | 列表或包含 map 方法的集合 |
each | string | 循环「项」变量名 | |
index | string | 循环「索引」变量名 |
注意,For
不能作为根元素
// 转换前{ index }. { item.title } // 转换前{ items.map( function(item, index) { { index }. { item.title } })}
用于将值赋给局部变量
// 简单用法{ foo } { bar } // 嵌套使用{ foo } { bar }
属性名 | 类型 | 必须 | 说明 |
---|---|---|---|
any | any | 将值赋给指定名称的局部变量 |
注意,定义的「变量」仅在 With 块中可用。
<With>
将会转换为一个「匿名的立即执行函数」
// 转换前{ foo } // 转换后{ (function(foo) { return { foo } }).call(this, 47)}
所有结构控制标签都是通过 Babel 插件进行转义的, 不需要 require
or import
,所有在进行「语法检查」时,将会出现「变量未定义」的警告或错误。
但是,有一个 ESlint 插件可处理这个问题
-- end --
转载地址:http://ugdgo.baihongyu.com/