開始使用JSX
JSX是React引入的一個技術。讓我們深入了解一下。
- JSX簡介
- JSX入門
- 轉譯JSX
- JS in JSX
- 在JSX中使用HTML
- React中的CSS
- JSX中的表單
- JSX自動轉義
- JSX中的空格
- 在JSX中添加註釋
- 擴展屬性
- 如何在JSX中進行循環
JSX簡介
JSX是由React引入的一項技術。
儘管React在不使用JSX的情況下也可以正常工作,但它是與組件一起工作的理想技術,因此React從JSX中獲益良多。
起初,您可能會認為使用JSX就像混合HTML和JavaScript(以及CSS)。
但事實並非如此,因為使用JSX語法時,實際上是用JavaScript編寫一個組件UI的聲明語法。
您使用的不是字符串描述UI,而是使用JavaScript,這使您能夠做許多好事。
JSX入門
以下是如何定義包含字符串的h1標籤的示例:
1 | const element = <h1>Hello, world!</h1> |
它看起來像JavaScript和HTML的奇怪混合,但實際上它是完全的JavaScript。
看起來像HTML,實際上是為了定義組件以及它們在標記中的定位而添加的語法糖。
在JSX表達式中,可以非常容易地插入屬性:
1 | const myId = 'test' |
只需注意,當屬性具有連字符(-)時,它會轉換為駝峰命名法。還有兩種特殊情況:
class
變成className
for
變成htmlFor
這是因為它們是JavaScript中的保留字。
以下是一個將兩個組件包裝到div標籤中的JSX片段的示例:
1 | <div> |
標籤始終需要關閉,因為這更像是XML而不是HTML(如果您還記得XHTML的日子,這將是熟悉的,但此後採用了HTML5鬆散語法)。在這種情況下,使用了自閉標籤。
請注意,我將2個組件包裝到div
中。為什麼?因為**render()
函數只能返回單個節點**,所以如果您要返回2個兄弟節點,只需添加一個父節點。它可以是任何標籤,不僅僅是div
。
轉譯JSX
瀏覽器無法執行包含JSX代碼的JavaScript文件。它們必須首先轉換為常規JS。
如何轉譯?通過進行所謂的轉譯過程。
我們已經說過JSX是可選的,因為對於每一個JSX行,都有一個對應的純JavaScript替代方案可用,這就是JSX轉譯的內容。
例如,以下兩個結構是等價的:
1 | ReactDOM.render( |
和
1 | ReactDOM.render( |
這個非常基本的例子只是起點,但您已經可以看到純JS語法與使用JSX相比有多麼複雜。
撰寫本文時,進行轉譯的最流行方法是使用Babel,這是在運行create-react-app
時的默認選項,因此如果您使用它,則無需擔心,一切都在幕後自動進行。
如果您不使用create-react-app
,則需要自行設置Babel。
JSX中的JS
JSX接受任何類型的JavaScript混合。
每當您需要添加一些JS時,只需將其放在大括號{}
中即可。例如,這是如何使用在其他地方定義的常量值:
1 | const paragraph = 'A paragraph' |
這是一個基本示例。大括號接受任何JS代碼:
1 | const paragraph = 'A paragraph' |
正如您所見,我們嵌套了JavaScript,該JavaScript定義在JSX內,而JSX定義在JavaScript中,您可以進行任意深度的嵌套。
JSX中的HTML
JSX在很大程度上與HTML類似,但實際上它是XML語法。
最終您要渲染HTML,所以您需要了解一些在HTML中如何定義某些內容以及如何在JSX中定義它們之間的差異。
您需要關閉所有標籤
就像在使用過XHTML的情況下一樣,您需要關閉所有標籤:不再是<br>
,而是使用自閉標籤<br />
(其他標籤也是如此)。
駝峰命名法是新的標準
在HTML中,您會找到沒有任何大小寫的屬性(例如onchange
)。在JSX中,它們被重命名為駝峰命名法:
onchange
=>onChange
onclick
=>onClick
onsubmit
=>onSubmit
class
變成className
由於JSX是JavaScript,而class
是保留詞,因此您不能寫
1 | <p class="description"> |
而是需要使用
1 | <p className="description"> |
**相同的適用於for
**,它被轉換為htmlFor
。
style屬性改變其語義
HTML中的style
屬性允許指定內聯樣式。在JSX中,它不再接受字符串,您將在React中的CSS中看到為什麼這是一個非常方便的更改。
表單
表單字段的定義和事件在JSX中進行了更改,以提供更一致性和實用性。
有關表單的更多細節,請參閱JSX中的表單。
React中的CSS
JSX提供了一種很酷的方式來定義CSS。
如果您對HTML內聯樣式有一點經驗,第一眼看起來,您會感覺自己被推到10或15年前的世界,在那裡內聯CSS是完全正常的(如今它被當作“快速修復”解決方案)。
JSX樣式與內聯CSS並不相同:首先,JSX style
屬性不像接受包含CSS屬性的字符串那樣,而僅接受一個對象。這意味著您在對象中定義屬性:
1 | var divStyle = { |
或者
1 | ReactDOM.render(<div style={{ color: 'white' }}>Hello World!</div>, mountNode) |
您在JSX中編寫的CSS值與普通CSS稍有不同:
- 屬性名稱的鍵以駝峰命名法命名
- 值只是字符串
- 您使用逗號分隔每組屬性
為什麼這比純CSS / SASS / LESS更受青睞?
CSS是一個未解決的問題。自從它問世以來,圍繞它的工具數不勝數。 CSS的主要問題在於它沒有作用域,並且很容易撰寫不受限制的CSS,因此“快速修復”可能會影響不應該觸及的元素。
JSX允許組件(例如在React中定義的組件)完全封裝其樣式。
這是首選解決方案嗎?
在JSX中的內聯樣式很好,直到您需要
- 編寫媒體查詢
- 規劃動畫
- 引用偽類(例如
:hover
) - 引用偽元素(例如
::first-letter
)
總之,它們涵蓋了基本功能,但不是最終解決方案。
JSX中的表單
JSX對HTML表單工作進行了一些更改,目的是使開發人員更容易使用。
value屬性和defaultValue屬性
value
屬性始終保存字段的當前值。
defaultValue
屬性保存在創建字段時設置的默認值。
這有助於解決常規DOM交互的一些奇怪行為,例如檢查input.value
和input.getAttribute('value')
返回一個返回當前值和一個返回原始默認值的情況。
這也適用於textarea
字段,例如
1 | <textarea>Some text</textarea> |
而不是
1 | <textarea defaultValue={'Some text'} /> |
對於select
字段,不使用
1 | <select> |
而使用
1 | <select defaultValue="x"> |
更一致的onChange事件
將函數傳遞給onChange
屬性,您可以訂閱表單字段上的事件。
它在不同的字段上以一致的方式工作,即使是radio
,select
和checkbox
輸入字段也會觸發onChange
事件。
在input
或textarea
字段中輸入字符時,onChange
事件也會觸發。
JSX自動轉義
為了減輕XSS攻擊的風險,JSX強制在表達式中自動轉義。
這意味著在字符串表達式中使用HTML實體時,可能會遇到問題。
您期望以下代碼將打印© 2020
:
1 | <p>{'© 2020'}</p> |
但它實際上打印的是© 2020
,因為字符串已轉義。
要解決此問題,您可以將實體移出表達式:
1 | <p>© 2020</p> |
或者通過使用打印HTML實體所對應的Unicode表示來使用常量:
1 | <p>{'\u00A9 2020'}</p> |
JSX中的空格
在JSX中添加空格有兩個規則:
水平空格被修剪為1個
如果在同一行上的元素之間有空格,則所有空格都被修剪為1個空格。
1 | <p>Something becomes this</p> |
變成
1 | <p>Something becomes this</p> |
垂直空格被消除
1 | <p> |
變成
1 | <p>Somethingbecomesthis</p> |
要解決此問題,您需要明確添加空格,只需添加一個空格表達式,如下所示:
1 | <p> |
或者通過在空格表達式中嵌入字符串來解決此問題:
1 | <p> |
在JSX中添加註釋
您可以使用正常的JavaScript註釋在表達式中添加註釋:
1 | <p> |
擴展屬性
在JSX中,常見的操作是為屬性分配值。
而不是手動執行,例如
1 | <div> |
您可以使用
1 | <div> |
並且data
對像的屬性將自動用作屬性,這得益於ES6的展開運算符。
如何在JSX中循環
如果您有一組元素需要進行循環以生成JSX片段,可以創建循環,然後將JSX添加到數組中:
1 | const elements = [] //..一些數組 |
現在在渲染JSX時,您可以將items
數組嵌入其中,方法是將其放在大括號中:
1 | const elements = ['one', 'two', 'three']; |
您也可以直接在JSX中執行相同操作,使用map
而不是for-of循環:
1 | const elements = ['one', 'two', 'three']; |
tags: [“JSX”, “React”, “CSS”, “HTML”, “forms”, “transpiling”, “comments”, “spread-attributes”, “loop”]