JSX 是 JavaScript 語(yǔ)法擴(kuò)展,可以讓你在 JavaScript 文件中書寫類似 HTML 的標(biāo)簽。雖然還有其它方式可以編寫組件,但大部分 React 開(kāi)發(fā)者更喜歡 JSX 的簡(jiǎn)潔性,并且在大部分代碼庫(kù)中使用它。
你將會(huì)學(xué)習(xí)到:
· 為什么 React 將標(biāo)簽和渲染邏輯耦合在一起
· JSX 與 HTML 有什么區(qū)別
· 如何通過(guò) JSX 展示信息
JSX: 將標(biāo)簽引入 JavaScript
網(wǎng)頁(yè)是構(gòu)建在 HTML、CSS 和 JavaScript 之上的。多年以來(lái),web 開(kāi)發(fā)者都是將網(wǎng)頁(yè)內(nèi)容存放在 HTML 中,樣式放在 CSS 中,而邏輯則放在 JavaScript 中 —— 通常是在不同的文件中!頁(yè)面的內(nèi)容通過(guò)標(biāo)簽語(yǔ)言描述并存放在 HTML 文件中,而邏輯則單獨(dú)存放在 JavaScript 文件中。
但隨著 Web 的交互性越來(lái)越強(qiáng),邏輯越來(lái)越?jīng)Q定頁(yè)面中的內(nèi)容。JavaScript 控制著 HTML 的內(nèi)容!這也是為什么 在 React 中,渲染邏輯和標(biāo)簽共同存在于同一個(gè)地方——組件。
將一個(gè)按鈕的渲染邏輯和標(biāo)簽放在一起可以確保它們?cè)诿看尉庉嫊r(shí)都能保持互相同步。反之,彼此無(wú)關(guān)的細(xì)節(jié)是互相隔離的,例如按鈕的標(biāo)簽和側(cè)邊欄的標(biāo)簽。這樣我們?cè)谛薷钠渲腥我庖粋€(gè)組件時(shí)會(huì)更安全。
每個(gè) React 組件都是一個(gè) JavaScript 函數(shù),它會(huì)返回一些標(biāo)簽,React 會(huì)將這些標(biāo)簽渲染到瀏覽器上。React 組件使用一種被稱為 JSX 的語(yǔ)法擴(kuò)展來(lái)描述這些標(biāo)簽。JSX 看起來(lái)和 HTML 很像,但它的語(yǔ)法更加嚴(yán)格并且可以動(dòng)態(tài)展示信息。了解這些區(qū)別最好的方式就是將一些 HTML 標(biāo)簽轉(zhuǎn)化為 JSX 標(biāo)簽。
JSX and React 是相互獨(dú)立的 東西。但它們經(jīng)常一起使用,但你 可以 單獨(dú)使用它們中的任意一個(gè),JSX 是一種語(yǔ)法擴(kuò)展,而 React 則是一個(gè) JavaScript 的庫(kù)。
將 HTML 轉(zhuǎn)化為 JSX
假設(shè)你現(xiàn)在有一些(完全有效的)HTML 標(biāo)簽:
<h1>海蒂·拉瑪?shù)拇k事項(xiàng)</h1>
<img
src="https://i.imgur.com/yXOvdOSs.jpg"
alt="Hedy Lamarr"
class="photo"
>
<ul>
<li>發(fā)明一種新式交通信號(hào)燈
<li>排練一個(gè)電影場(chǎng)景
<li>改進(jìn)頻譜技術(shù)
</ul>
而現(xiàn)在想要把這些標(biāo)簽遷移到組件中:
export default function TodoList() {
return (
// ???
)
}
如果直接復(fù)制到組件中,并不能正常工作:

這是因?yàn)?JSX 語(yǔ)法更加嚴(yán)格并且相比 HTML 有更多的規(guī)則!上面的錯(cuò)誤提示可以幫助你修復(fù)標(biāo)簽中的錯(cuò)誤,當(dāng)然也可以參考下面的指引。
大部分情況下,React 在屏幕上顯示的錯(cuò)誤提示就能幫你找到問(wèn)題所在,如果在編寫過(guò)程中遇到問(wèn)題就參考一下提示吧。
JSX 規(guī)則
1. 只能返回一個(gè)根元素
如果想要在一個(gè)組件中包含多個(gè)元素,需要用一個(gè)父標(biāo)簽把它們包裹起來(lái)。
例如,你可以使用一個(gè) <div> 標(biāo)簽:
<div>
<h1>海蒂·拉瑪?shù)拇k事項(xiàng)</h1>
<img src="https://i.imgur.com/yXOvdOSs.jpg" alt="Hedy Lamarr" class="photo" >
<ul> ... </ul>
</div>
如果你不想在標(biāo)簽中增加一個(gè)額外的 <div>,可以用 <> 和 </> 元素來(lái)代替:
<>
<h1>海蒂·拉瑪?shù)拇k事項(xiàng)</h1>
<img src="https://i.imgur.com/yXOvdOSs.jpg" alt="Hedy Lamarr" class="photo" >
<ul> ... </ul>
</>
這個(gè)空標(biāo)簽被稱作 Fragment。React Fragment 允許你將子元素分組,而不會(huì)在 HTML 結(jié)構(gòu)中添加額外節(jié)點(diǎn)。
為什么多個(gè) JSX 標(biāo)簽需要被一個(gè)父元素包裹?
JSX 雖然看起來(lái)很像 HTML,但在底層其實(shí)被轉(zhuǎn)化為了 JavaScript 對(duì)象,你不能在一個(gè)函數(shù)中返回多個(gè)對(duì)象,除非用一個(gè)數(shù)組把他們包裝起來(lái)。這就是為什么多個(gè) JSX 標(biāo)簽必須要用一個(gè)父元素或者 Fragment 來(lái)包裹。
2. 標(biāo)簽必須閉合
JSX 要求標(biāo)簽必須正確閉合。像 <img> 這樣的自閉合標(biāo)簽必須書寫成 <img />,而像 <li>oranges 這樣只有開(kāi)始標(biāo)簽的元素必須帶有閉合標(biāo)簽,需要改為 <li>oranges</li>。
海蒂·拉瑪?shù)恼掌痛k事項(xiàng)的標(biāo)簽經(jīng)修改后變?yōu)椋?/p>
<>
<img
src="https://i.imgur.com/yXOvdOSs.jpg"
alt="Hedy Lamarr"
class="photo"
/>
<ul>
<li>發(fā)明一種新式交通信號(hào)燈</li>
<li>排練一個(gè)電影場(chǎng)景</li>
<li>改進(jìn)頻譜技術(shù)</li>
</ul>
</>
3. 使用駝峰式命名法給 大部分 屬性命名!
JSX 最終會(huì)被轉(zhuǎn)化為 JavaScript,而 JSX 中的屬性也會(huì)變成 JavaScript 對(duì)象中的鍵值對(duì)。在你自己的組件中,經(jīng)常會(huì)遇到需要用變量的方式讀取這些屬性的時(shí)候。但 JavaScript 對(duì)變量的命名有限制。例如,變量名稱不能包含 - 符號(hào)或者像 class 這樣的保留字。
這就是為什么在 React 中,大部分 HTML 和 SVG 屬性都用駝峰式命名法表示。例如,需要用 strokeWidth 代替 stroke-width。由于 class 是一個(gè)保留字,所以在 React 中需要用 className 來(lái)代替。這也是 DOM 屬性中的命名:
<img src="https://i.imgur.com/yXOvdOSs.jpg" alt="Hedy Lamarr" className="photo"/>
你可以 在 React DOM 元素中找到所有對(duì)應(yīng)的屬性。如果你在編寫屬性時(shí)發(fā)生了錯(cuò)誤,不用擔(dān)心 —— React 會(huì)在 瀏覽器控制臺(tái) 中打印一條可能的更正信息。
高級(jí)提示:使用 JSX 轉(zhuǎn)化器
將現(xiàn)有的 HTML 中的所有屬性轉(zhuǎn)化 JSX 的格式是很繁瑣的。我們建議使用 轉(zhuǎn)化器 將 HTML 和 SVG 標(biāo)簽轉(zhuǎn)化為 JSX。這種轉(zhuǎn)化器在實(shí)踐中非常有用。但我們依然有必要去了解這種轉(zhuǎn)化過(guò)程中發(fā)生了什么,這樣你就可以編寫自己的 JSX 了。
這是最終的結(jié)果:
