一些開發者,特別是有使用過「模板技術」的開發者(例如 Handlebars),剛開始嘗試使用 React 編寫應用時,可能會驚訝的發現,JSX 居然沒有內建支持相似其它模板引擎似的任何結構控制語句或指令。但這就是 JSX,它就是這麼設計的,JSX 不是傳統的模板,也不須要某個模板引擎去解析。大致上,能夠將 JSX 當作普通 JavaScript 表達式的語法糖。javascript
下邊的的代碼是一個「普通的 JavaScript 代碼示例」java
render () { return (if(true){ ... }else{ ... }); }
如上代碼不合法的,一樣,下邊的 jsx 代碼也是不合法的git
render () { return (<div> {if(true) <span>1</span> else <span>2</span> } </div>); }
由於,JavaScript 不能在一個「表達式」中嵌入「控制語句」。github
JSX-Control-Statements 爲 JSX 增長了基本的結構控制語句,好比條件和循環控制語句。經過將插件將「組件風格」的控制語句最終轉換爲普通 JS 代碼,例如:npm
<If condition={condition()}>Hello World!</If>
將會轉換爲json
condition() ? 'Hello World!' : null
這看起來,彷佛很容易實現,經過一系列表組件好像就能實現,但事實上這在 React 中這是不可行的,若是用「組件」的方式實現,相似以下代碼babel
<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 方法還麻煩。ui
因此,JSX Control Statements
是一個 Babel 插件,採起了在「編譯階段」將「控制標籤」轉換爲「普通的 JavaScript 表達式」的方案,最終編譯結果和原來的寫法沒有什麼不一樣。this
須要先行安裝好 Babel,以後經過 npm 安裝 jsx-control-statements
npm install --save-dev jsx-control-statements
還須要在 .babelrc
中配置插件,以下
{ ... "plugins": ["jsx-control-statements"] }
用來表示最簡單的條件判斷邏輯
// 簡單示例 <If condition={ true }> <span>IfBlock</span> </If> // 包括多個子元素及表達式 <If condition={ true }> one { "two" } <span>three</span> <span>four</span> </If>
if 的 body 部分只有在 condition 爲 true 纔會渲染
屬性名 | 類型 | 必須 |
---|---|---|
condition | boolean | 是 |
Eles 已廢棄,不推薦使用,它會破壞 JSX/XML 的語法,而且影響自動格式化。
If 標籤將會預編譯爲「三元表達式」
// 轉換前 <If condition={ test }> <span>Truth</span> </If> // 轉換後 { test ? <span>Truth</span> : null }
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 的子元素只容許出現 When
和 Otherwise
,其中最少須要有一個 When
,而 Otherwise
是可選的
和 <If>
相似
屬性名 | 類型 | 必須 |
---|---|---|
condition | boolean | 是 |
沒有任何一個 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
的命名用方法,以下
// 注意,須要指定 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 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 相互隔斷致使的代碼「支離破碎」
更好的可讀性和整潔,不過這取決於你的我的喜愛。
多了一步編譯,會多用一點點構建時間
依賴 Bable 6,並須要配置一下 .babelrc
全部結構控制標籤都是經過 Babel 插件進行轉義的, 不須要 require
or import
,全部在進行「語法檢查」時,將會出現「變量未定義」的警告或錯誤。
可是,有一個 ESlint 插件可處理這個問題
ESLint plugin for JSX-Control-Statements
-- end --