JSX 背後的真相:它是怎麼轉換成畫面的?
更新日期: 2025 年 3 月 30 日
本文為 JSX 基礎介紹系列文:
- React 中的 JSX 是什麼?為什麼它長得像 HTML?
- JSX 與 HTML 的差異:5 個常見新手錯誤一次搞懂
- JSX 中如何插入 JavaScript?使用 {} 的基本原則
- JSX 中的條件渲染與清單渲染:實用範例教學
- JSX 背後的真相:它是怎麼轉換成畫面的?
閱讀完本系列文後,可以繼續閱讀《React 元件基礎介紹》介紹
如果你剛開始學習 React,一定對 JSX 感到既熟悉又陌生。
它看起來像是 HTML,卻能夠寫在 JavaScript 裡。你可能曾經寫過像這樣的程式碼:
const element = <h1>Hello, world!</h1>;
但你有沒有想過,瀏覽器並不認識 <h1>
是什麼 JavaScript 物件,那這樣的語法到底是怎麼變成畫面的?這背後發生了什麼事?
本篇文章將帶你揭開 JSX 背後的真相,從 Babel 的轉譯過程,到 React.createElement
的角色,最後簡單介紹虛擬 DOM(Virtual DOM),讓你理解 JSX 是怎麼一步步變成畫面的!
什麼是 JSX?
看起來像 HTML,其實是 JavaScript 的語法糖。
JSX,全名是 JavaScript XML,是 React 所採用的一種語法擴充形式。
它讓我們可以在 JavaScript 中直接寫出類似 HTML 的標籤語法,用來描述 UI 的結構,這不僅更直觀,也更貼近我們在設計畫面時的思考方式。
來看看這個簡單的範例:
const greeting = <p>Hello, React!</p>;
這段程式碼看起來就像是 HTML 的 <p>
標籤包著文字內容,但它實際上寫在 JavaScript 的變數裡,並且被賦值給 greeting
這個變數。
這樣的語法,在 React 世界裡非常常見,不論是建立元件還是組合畫面,都會大量使用。
為什麼說 JSX 是語法糖?
所謂「語法糖」(syntactic sugar)指的是讓程式碼更好讀、寫起來更方便的語法表達方式,實際上這些語法在編譯後,會被轉換成更基礎的語法格式。
在 JSX 的情境中,我們表面上寫的是 HTML 標籤,但這些語法在被 React 處理之前,會先經過 Babel 編譯器的轉換,最終變成純 JavaScript 語法,才能被瀏覽器理解並執行。
換句話說,<p>Hello, React!</p>
只是寫起來舒服的一種表示方法,背後其實還有一整套轉換與處理的機制。
瀏覽器其實不懂 JSX!
這點對初學者非常重要:瀏覽器並不能直接執行 JSX。
如果你把含有 JSX 的程式碼直接放在 <script>
標籤裡,瀏覽器會立刻報錯。
這是因為 JSX 並不是 JavaScript 的標準語法,必須要透過像 Babel 這樣的工具先「轉譯」成瀏覽器認識的語法(例如呼叫 React.createElement
函式),之後才能順利顯示出你想要的畫面。
例如這段 JSX:
const greeting = <p>Hello, React!</p>;
會被 Babel 轉譯成這樣的 JavaScript 程式碼:
const greeting = React.createElement('p', null, 'Hello, React!');
這才是瀏覽器可以執行的程式碼,也才是 React 能進一步使用來建立虛擬 DOM 的資料格式。
JSX 就像是寫給開發者看的 UI 描述語言,它讓我們寫 UI 更直覺、更接近設計師的思維。
但要記住,它不是原生 JavaScript,更不是瀏覽器能直接理解的語法。
這也正是我們接下來要介紹 Babel 與 React.createElement 的原因 —— 它們負責把這段「語法糖」轉換成真正能工作的 JavaScript 程式碼。
Babel:負責把 JSX 轉換成 JavaScript 的工具
Babel 是什麼?
Babel 是一個廣泛使用的 JavaScript 編譯器(compiler)。
主要目的是將開發者撰寫的「現代 JavaScript 語法」—— 像是 ES6、ES7 甚至是 JSX —— 轉換成舊版瀏覽器也能看得懂的「標準 JavaScript 語法」。
這樣的轉譯過程可以讓我們使用最新、最方便的語法,同時也保證應用程式在大多數使用者的瀏覽器中都能正常執行。
對於 React 開發者來說,Babel 最重要的任務之一,就是負責將我們寫的 JSX 轉換成標準的 JavaScript 函式呼叫,因為瀏覽器本身不支援 JSX。
JSX 是怎麼被 Babel 處理的?
來看看一段我們在 React 中常見的 JSX 程式碼:
const element = <h1>Hello, world!</h1>;
這樣的寫法雖然直覺好懂,但瀏覽器根本不會認得 <h1>
是什麼 JavaScript 元素,因此這段程式碼沒辦法直接執行。
這時 Babel 就會出場,它會將這段程式碼轉譯成等效的 JavaScript 語法:
const element = React.createElement('h1', null, 'Hello, world!');
轉譯後的語法使用了 React 提供的 createElement
函式,這個函式會產生一個虛擬 DOM 物件,讓 React 知道要在畫面上顯示什麼內容。
Babel 做了哪些事情?
從技術角度來說,Babel 會進行三個主要步驟:
- Parsing(解析):將程式碼轉成一種稱為 AST(抽象語法樹,Abstract Syntax Tree)的資料結構。
- Transformation(轉換):修改這棵 AST,把 JSX 語法節點改寫成對應的
React.createElement
語法。 - Code Generation(產出):將修改後的 AST 轉換成新的 JavaScript 程式碼,也就是轉譯後的結果。
這整個流程對開發者來說是透明的,你只需要設定好 Babel,它就會在背後幫你處理所有繁瑣的轉換工作。
補充:Babel 的替代方案
Babel 雖然是最主流的 JavaScript 轉譯器,但隨著前端工具鏈演進,也有其他轉譯器被開發出來,有些甚至比 Babel 更快、更輕量。
以下是幾個常見可以取代 Babel 的 JavaScript 轉譯工具:
工具 | 支援 JSX | 支援 TypeScript | 編譯速度 | 成熟度 | 備註 |
---|---|---|---|---|---|
Babel | ✅ | ✅ | 慢 | 非常高 | 功能齊全、社群廣泛 |
SWC | ✅ | ✅ | 快速 | 高 | 下一代主流,React 官方採用 |
esbuild | ✅ | ✅ | 超快 | 中高 | 適合輕量開發工具與 Vite |
RSPack | ✅ | ✅ | 快速 | 新興 | 與 Webpack 相容的新選擇 |
如果你是初學者,Babel 還是最容易理解和上手的工具;但如果你追求高效開發體驗,學習使用 SWC 或 esbuild 也絕對值得!
Babel + Webpack:React 專案的組合常客
在建立 React 專案時,通常會搭配使用 Babel 和 Webpack。
Webpack 是一個模組打包工具,而 Babel 則是其中負責「語法轉譯」的角色。
你可以透過設定 .babelrc
或 babel.config.js
來定義 Babel 要轉譯哪些語法(例如加上 @babel/preset-react
來支援 JSX)。
例如:
{
"presets": ["@babel/preset-env", "@babel/preset-react"]
}
這樣的設定讓 Babel 能夠轉譯包含 JSX 和現代 JavaScript 的程式碼,確保在任何瀏覽器中都能正確運行。
你可以把 Babel 想像成一台語言翻譯機,它幫你把開發者喜歡用的「漂亮語法」翻譯成「瀏覽器聽得懂」的 JavaScript。
你寫的是 JSX → Babel 轉譯 → React 的 JavaScript 語法 → 顯示畫面
沒有 Babel,React 專案中的 JSX 就無法發揮作用;而有了 Babel,開發者可以放心使用最新語法,同時兼顧相容性與維護性。
React.createElement:幫你生成虛擬 DOM 的函式
它是 JSX 的「實際執行者」
在上一節我們提到,JSX 本質上只是語法糖,而 Babel 在背後會將 JSX 轉譯成標準 JavaScript。
這個轉譯的結果幾乎都會呼叫一個核心函式:React.createElement
。
這個函式可以說是 JSX 的真正執行版本。每當你寫下一段像這樣的 JSX:
const element = <h1>Hello, world!</h1>;
Babel 會幫你轉換成:
const element = React.createElement('h1', null, 'Hello, world!');
這樣的程式碼才是真正會被 React 執行的 JavaScript。
React.createElement 做了什麼?
React.createElement
並不會直接產生 HTML,也不會直接修改畫面上的 DOM。
它的目的是建立一個「虛擬 DOM 物件(Virtual DOM Object)」,這個物件是一種 JavaScript 資料結構,用來描述畫面中應該出現什麼內容。
舉個例子,這行程式碼:
const element = React.createElement('h1', null, 'Hello, world!');
會產生一個 JavaScript 物件如下:
{
type: 'h1',
props: {
children: 'Hello, world!'
}
}
這個物件就像是在說:「我想要畫一個 <h1>
,裡面有文字 ‘Hello, world!’」,但它還沒有真的出現在畫面上,只是存在記憶體裡的一段資料結構。
參數說明
React.createElement
的語法如下:
React.createElement(type, props, ...children)
參數名稱 | 說明 |
---|---|
type | 元素類型,像是 'div'、'h1',也可以是自訂的 React 元件。 |
props(properties 簡寫) | 傳入該元素的屬性,像是 className、id 等。若無屬性可傳入 null。 |
children | 元素的內容或子元素,可以是文字、另一個元素、陣列等。 |
範例:
const element = (
<button className="my-btn">
Click me!
</button>
);
轉譯後為:
const element = React.createElement(
'button',
{ className: 'my-btn' },
'Click me!'
);
為什麼不直接建立 HTML?
你可能會想:既然目的是呈現畫面,為什麼不直接產生 <h1>
標籤或使用 document.createElement
?
這樣設計的好處有很多,最核心的原因就是為了實作 虛擬 DOM(Virtual DOM)機制:
- 先在記憶體中構建畫面描述(虛擬 DOM)
- 等有需要時,再由 React 決定哪些部分真的要更新到真實 DOM 上
這樣一來可以大幅減少對 DOM 的直接操作,避免每次畫面變化都整個重繪,有效提升瀏覽器效能與使用者體驗。
React.createElement 與虛擬 DOM 的關係
可以這樣理解:
- JSX 是畫面結構的語法糖
- Babel 將 JSX 轉譯成 React.createElement
- React.createElement 建立虛擬 DOM 的 JavaScript 物件
- React 利用這些虛擬 DOM 資料,來計算並更新真實 DOM
這一層層的轉換看似繞路,實際上卻讓開發者撰寫簡單、維護方便、效能優化自動化。
虛擬 DOM(Virtual DOM):畫面更新的秘密武器
虛擬 DOM 是什麼?
在 React 中,虛擬 DOM(Virtual DOM,簡稱 VDOM)是一個非常核心、也非常聰明的設計概念。
簡單來說,虛擬 DOM 就是一種 用 JavaScript 物件來模擬真實 DOM 結構的技術。
也就是說,它不是實際存在於畫面上的 HTML,而是存在於記憶體中的一份畫面結構描述。
你可以想像它像是網頁畫面的「快照」、「藍圖」或「畫面草圖」,React 會根據這份藍圖來決定什麼時候該動手去更新畫面。
舉個例子幫助理解:
當你寫下這段 JSX:
const element = <h1>Hello, React!</h1>;
經過 React.createElement
的處理後,React 並不會直接在畫面上插入一個 <h1>
,而是會先在記憶體中建立這樣的一個 JavaScript 物件:
{
type: 'h1',
props: {
children: 'Hello, React!'
}
}
這個物件就是虛擬 DOM,它描述了「我要畫一個 h1,裡面放這段文字」。
虛擬 DOM 的真正用處在哪?
🔁 1. 畫面更新時,React 不會馬上修改真實 DOM
傳統的 DOM 操作(像是 jQuery)只要資料一變動,就直接動手改畫面,這會帶來以下問題:
- 每次都要操作真實 DOM → 效能低下
- 程式邏輯變複雜 → 難以維護
而 React 的做法是這樣的:
- 你更新資料(state、props)
- React 重新產生一棵新的虛擬 DOM
- 把「新的虛擬 DOM」和「舊的虛擬 DOM」做比較
- 找出哪些地方真的變了
- 只針對變動的部分,更新真實 DOM
這個比較的過程就叫做 Diffing(差異比較),是一種高效演算法,幫助 React 瞬間找出畫面該更新的區塊。
🧠 2. React 幫你管理畫面狀態與更新邏輯
開發者只需要用 JSX 描述畫面長什麼樣子,React 會根據資料變化,幫你算出「要怎麼更新」,大大減少人為操作 DOM 的錯誤機率。
為什麼這麼做效能更好?
真實 DOM 是瀏覽器中非常「昂貴」的一部分,意思是:
- 改動一次,瀏覽器就可能需要重新排版、重新繪製
- 若你頻繁改動 DOM,畫面就可能卡頓或掉幀
而虛擬 DOM 的比較和操作都發生在記憶體中,是用 JavaScript 執行、速度快、成本低的邏輯處理。React 只會在真正必要時,才觸發 DOM 更新,這樣就能有效提升整體效能與使用者體驗。
虛擬 DOM 的優點總整理
✅ 效能更好
React 不直接對真實 DOM 進行每一次的小修改,而是等計算好哪些部分該改,再批次更新,這樣可以減少重新渲染的開銷。
✅ 易於維護
開發者不用自己追蹤資料變化與畫面同步,只要更新狀態,React 就會幫你負責把畫面對應好。
✅ 跨平台潛力
虛擬 DOM 的概念不受限於「瀏覽器 DOM」,它只是一種「畫面描述的資料結構」。
這讓 React 能夠延伸到像 React Native、React VR 等平台,生成手機原生 UI 或 3D 畫面,跨越平台使用。
小結:虛擬 DOM 就像 React 的智慧大腦
傳統方式:資料變了 → 你手動改 DOM
React 方式:資料變了 → React 幫你比較兩份虛擬 DOM → 自動更新該更新的地方
虛擬 DOM 是 React 能做到「資料驅動畫面」(data-driven UI)與「高效更新」的基石。
如果你搞懂這一層邏輯,會對 React 整體架構有更深入的理解。
總結
- 你寫下 JSX:像
<h1>Hello</h1>
。 - Babel 轉譯:變成
React.createElement(...)
。 - React.createElement 回傳虛擬 DOM:也就是 JavaScript 物件。
- React 用虛擬 DOM 渲染畫面:將虛擬 DOM 轉成真實 DOM,或比對更新。
了解這整個流程,有助於你更深入掌握 React 的底層原理,未來在除錯或優化時也更有方向。