JSX 的語法規則脈絡與畫面渲染的實用技巧
嚴格標籤閉合
說明
在 JSX 中,所有標籤都必須嚴格閉合,這與 HTML 有些不同。HTML 允許某些標籤(如 <input>
、<br>
)不閉合,但在 JSX 中,無論是普通標籤還是自訂義元件,必須明確閉合,否則會報錯。這是因為 JSX 最終會被轉譯成 JavaScript 的 React.createElement 函數,該函數需要完整的標籤結構。
實用技巧
-
自閉合標籤:對於沒有子元素的標籤,使用自閉合形式,例如
<input />
或<MyComponent />
。 -
成對標籤:有子元素的標籤必須有開頭和結尾,例如
<div>
...</div>
。 -
檢查工具:使用 ESLint 或 Prettier 等工具,確保標籤閉合正確,避免手動疏忽。
程式碼範例
import React from "react";
function App() {
return (
<div>
{/* 正確:自閉合標籤 */}
<input type="text" />
{/* 正確:成對標籤 */}
<p>這是一個段落</p>
{/* 錯誤:未閉合標籤 */}
{/* <input type="text"> */}
{/* 錯誤:缺少結尾標籤 */}
{/* <div>這是 div */}
</div>
);
}
export default App;
操作步驟
-
建立一個新的 React 專案(可使用 create-react-app 或 Vite)。
-
在 src/App.jsx 中貼上上述程式碼。
-
啟動專案(npm start 或 yarn start),檢查瀏覽器是否正確渲染。
-
嘗試移除某個標籤的閉合(例如
<input>
不加 /),觀察報錯訊息,了解 JSX 的嚴格要求。
JSX 語法中的資料表達
說明
JSX 允許在標籤中使用 JavaScript 表達式來動態顯示資料。表達式必須放在大括號 中,且只能是單一表達式(不能是語句,如 if 或 for)。這使得 JSX 可以靈活地根據變數、狀態或屬性動態渲染內容。
實用技巧
-
變數與運算:在大括號中放入變數、運算結果或函數調用。
-
條件渲染:使用三元運算子或邏輯運算符(&&)來控制內容顯示。
-
陣列映射:用 map 方法動態渲染列表,記得為每個子元素加上獨特的 key 屬性。
程式碼範例
import React, { useState } from "react";
function App() {
const name = "小明";
const age = 25;
const fruits = ["蘋果", "香蕉", "橘子"];
const [isLoggedIn, setIsLoggedIn] = useState(false);
return (
<div>
{/* 變數 */}
<h1>你好,{name}!</h1>
{/* 運算 */}
<p>明年你將會是 {age + 1} 歲</p>
{/* 條件渲染 */}
<p>{isLoggedIn ? "歡迎回來!" : "請先登入"}</p>
<button onClick={() => setIsLoggedIn(!isLoggedIn)}>
{isLoggedIn ? "登出" : "登入"}
</button>
{/* 陣列映射 */}
<ul>
{fruits.map((fruit, index) => (
<li key={index}>{fruit}</li>
))}
</ul>
</div>
);
}
export default App;
操作步驟
-
在 src/App.jsx 中貼上上述程式碼。
-
確保已安裝 React(若使用 create-react-app,預設已包含)。
-
啟動專案,觀察瀏覽器中動態顯示的名字、年齡、登入狀態和水果列表。
-
點擊「登入/登出」按鈕,確認條件渲染是否正確切換。
-
嘗試修改 fruits 陣列或 name 變數,觀察畫面變化。
畫面渲染邏輯
說明
JSX 的畫面渲染邏輯主要依賴 React 的元件和狀態管理。React 會根據元件的狀態(state)或屬性(props)變化,自動重新渲染畫面。開發者需要理解如何組織渲染邏輯,以提高效率並避免不必要的重新渲染。
實用技巧
-
狀態管理:使用 useState 管理元件狀態,觸發畫面更新。
-
條件渲染:結合三元運算子或邏輯運算符實現動態顯示。
-
避免重複渲染:使用 React.memo 或 useMemo 優化性能。
-
事件處理:透過事件處理函數更新狀態,驅動畫面變化。
程式碼範例
import React, { useState, useMemo } from "react";
function App() {
const [count, setCount] = useState(0);
const [showText, setShowText] = useState(true);
const largeArray = Array.from({ length: 10000 }, (_, i) => i + 1);
// 使用 useMemo 避免每次渲染都過濾陣列
const filteredArray = useMemo(() => {
console.log("執行陣列過濾");
return largeArray.filter((num) => num % count === 0);
}, [count]);
return (
<div>
<h1>計數:{count}</h1>
<button onClick={() => setCount(count + 1)}>增加</button>
{showText && <p>這段文字可以隱藏</p>}
<button onClick={() => setShowText(!showText)}>切換文字</button>
<p>過濾結果數量:{filteredArray.length}</p>
</div>
);
}
export default App;
操作步驟
-
過濾一個包含 10,000 個元素的大陣列是一項昂貴的操作。
-
如果沒有 useMemo,每次點擊「切換文字」按鈕(改變 showText)都會重新過濾陣列,導致性能問題。
為什麼一段 JSX 語法的第一層只能有一個節點
說明
JSX 的第一層只能有一個根節點,這是因為 JSX 最終會被轉譯成 React.createElement 函數的單一調用,而該函數只能接受一個根元素作為返回值。若有多個並列元素,React 無法確定如何處理,因此會報錯。
解決方法
-
使用 div 包裝:將多個元素包在一個
<div>
中。 -
使用 Fragment:使用
<React.Fragment>
或簡寫<>
包裝多個元素,避免多餘的 DOM 節點。 -
檢查結構:確保 JSX 的結構清晰,避免無意中返回多個並列節點。
程式碼範例
import React from "react";
function App() {
return (
<>
{/* 使用 Fragment 包裝多個元素 */}
assets/app.jsx
<h1>標題</h1>
<p>這是一個段落</p>
{/* 錯誤:多個並列節點 */}
{/* <h1>標題</h1> */}
{/* <p>段落</p> */}
{/* 使用 div 包裝 */}
<div>
<h2>另一個標題</h2>
<p>另一個段落</p>
</div>
</>
);
}
export default App;
操作步驟
-
在 src/App.jsx 中貼上上述程式碼。
-
啟動專案,確認畫面正常顯示標題和段落。
-
嘗試移除
<>
或<div>
,直接返回多個並列元素(例如<h1>
和<p>
),觀察報錯訊息。 -
在瀏覽器開發者工具中檢查 DOM 結構,確認
<>
不會產生多餘的 DOM 節點,而<div>
會。
總結
-
嚴格標籤閉合:確保所有標籤正確閉合,避免語法錯誤。
-
資料表達:使用大括號 插入 JavaScript 表達式,實現動態渲染。
-
畫面渲染邏輯:透過狀態管理和優化工具(如 useMemo)控制渲染行為。
-
單一節點限制:使用
<>
或<div>
包裝多個元素,滿足 JSX 的單一根節點要求。
如果您有其他問題或需要更詳細的範例,請隨時告訴我!