JSX 是 react 打包的一種 JS 標籤語法,它其實不是字串或 HTML,不過 JSX 是基於 HTML 的特性使用 JS 開發出來的,因此擁有 HTML 大部分的特性,可以當作 HTML 使用,React 中我們使用 JSX 來寫 HTML 的標籤。
其實 JSX 是為 React.createElement
函式提供的語法糖,React.createElement
主要是用於生成 React Elements,這是一種 Virtual DOM ,Virtual DOM 經過比較和計算後再渲染成原生 DOM。使用 Virtual DOM 是因為 React 希望當資料有更新時,頁面可以自動重新渲染,但是渲染整個頁面相對花費的時間及資源都比較多,因此才需要 Virtual DOM 的幫助,在資料更新時,先重新繪製 Virtual DOM 與 Real DOM 做比對,有變動的地方才去做更新。
class
對應 className
。在 JSX 中,所有的事件名和屬性名都,只要是由超過兩個單字以上組成都需要使用駝峰式命名,除了 aria-*
及 data-*
屬性名,例子如下:
<input type="text" minLength="10" />
事件名例子如下:
// 在 html 中是 onclick
<button onClick={() => alert('已經送出')}>送出</button>
使用 inline style 時,也有部分 CSS 屬性需要駝峰命名,因為 style 在 JSX 中接受的實際上是物件,因此屬性名稱是多於兩個以上的單字,通常都要駝峰命名
<input type="text" style={{backgroundColor: 'red', fontSize: 15}} />
在 JSX 中,部分屬性名和 HTML 不同。
class
改為 className
<input type="text" className="colorClass" />
defaultValue
: 在 JSX 中 input
除了使用 value
外,還可以使用 defaultValue
來設置第一次裝載時候的默認值。<input type="text" value="固定值" />
<input type="text" defaultValue="初始默認值" />
checked
和 defaultChecked
: checked
可以用於判斷 checkbox
和 radio
是否被選中,defaultChecked
可以設置第一次裝載時候,默認選中的值。<input type="radio" checked="checked" />白色
<input type="radio" defaultChecked={true} />紅色
innerHTML
和 dangerouslySetInnerHTML
: dangerouslySetInnerHTML
相當於 HTML 的 innerHTML
,React 中沒有 innerHTML
這個屬性,所以使用 dangerouslySetInnerHTML
來插入 HTML 字串。dangerouslySetInnerHTML
的值必須是一個物件,物件中使用 __html
來接受字串,如下const htmlStr = '<h1>title</h1>';
<App>
<div dangerouslySetInnerHTML={{__html: htmlStr}}></div>
</App>
基本上 JSX 的使用方式,就是直接在裡面寫 HTML 標籤即可,如下:
const App = () => {
return <div>
<span>JSX</span>
</div>
}
JSX 中可以使用 {} 來輸入 JS 表達式,另外 JSX 也可以作為表達式賦給變數使用
const Profile = (props) => {
const {name} = props;
const nameTitle = <h1>Profile</h1>
return <div>
{ nameTitle }
<span>My name is { name }</span>
</div>
}
傳遞參數時,如果是變數、數值或布林,也需要使用 {} 來傳遞,如果是字串則不用
const Profile = (props) => {
const {name} = props;
const nameTitle = <h1>Profile</h1>
return <div>
{ nameTitle }
<span>My name is { name }</span>
<ProfileData
age={31}
gender="male"
/>
</div>
}
// 在子組件輸出
const ProfileData = ({age, gender}) => {
return <div>
<p>age: {age}</p>
<p>gender: {gender}</p>
</div>
}
JSX 中,可以直接在事件後面用表達式,或是將函式賦在變數上呼叫,如下面的範例,將一個函式賦在 sendEvent
上,之後在元件中呼叫 sendEvent
來調用函式:
const Profile = (props) => {
const sendEvent = () => {
console.log('送出成功')
}
return <div>
<button onClick={sendEvent}></button>
<button onClick={() => console.log('送出成功')}></button>
</div>
}
JSX 中加載圖片有兩種方式,一種是用 require
,一種是用 import
,如果是用 import
,必須先賦給一個變數,再去調用變數。
import Img from './test.png'
const Profile = (props) => {
return <div>
<img src={require("./test.png")} />
<img src={Img} />
</div>
}
JSX 中不能直接使用 if else
判斷,但可以使用三元運算子判斷,例如下面的範例,用三元運算子判斷是否 loading
const App = ({loading}) => {
return <div>
{loading ? <div>下載中...</div> : null}
</div>
}
也可以在三元運算子中再使用三元運算子判斷,如下
const App = ({loading, name}) => {
return <div>
{
loading ?
name ? <span>{name}</span> : null
: null
}
</div>
}
另外,也可以使用 &&
來做判斷,如下面範例,當 loading
為 true
的時候,後面的 <div>下載中...</div>
也會一起顯示
const App = ({loading}) => {
return <div>
{loading && <div>下載中...</div>}
</div>
}
也可以在 JSX 之前使用 if
判斷,把判斷的結果交給變數,輸出到 JSX 中,如下
const App = ({user}) => {
let isLogin = flase;
if (user && user.id) isLogin = true;
return <div>
{isLogin ? <div>你已經登入</div> : <div>尚未登入</div>}
</div>
}
但上面這種作法,一般比較少人使用,通常都是將判斷直接寫在 JSX 中。
JSX 中渲染多個標籤或元件不難,但是會有許多種情況,這邊就讓我們一個個了解。
React 組件可以返回封閉的標籤或字串,但不支持直接返回列表,如下面的情況,就是錯誤例子
//錯誤範例
const App = () => {
return (
<li></li>
<li></li>
<li></li>
)
}
這種情況下,我們必須用 Fragment
來包住列表。Fragment
是 jsx 用來包住列表或多個標籤用的,其本身不會生成額外標籤,如下
import React, { Fragment } from 'react';
const App = () => {
return <Fragment>
<li></li>
<li></li>
<li></li>
</Fragment>
}
<></>
包住列表<></>
其實是 Fragment
的簡寫,不過有部分工具可能不支援這種寫法
import React from 'react';
const App = () => {
return <>
<li></li>
<li></li>
<li></li>
</>
}
JSX 中,陣列資料的渲染,通常都是使用 map
,另外要注意的是,React 中規定,渲染陣列資料時,每一筆資料都必須有 key
屬性,key
能幫助 React 確認哪一筆資料被修改或移除,每一筆 key
都是獨有的,不能重複。
const App = (props) => {
const { lists = [] } = props;
return (
<div>
{
lists.map(item =>
<div key={item.id}>
<div>{item.name}</div>
<div>{item.age}</div>
<div>{item.gender}</div>
</div>
)
}
</div>
)
}
JSX 常見的用法雖然原本就知道,但我並不是全部都清楚程式碼實際上的運作方式,因此特地在這一篇中整理了一次。下一篇開始會整理一些 React 中常見,但我比較不熟悉的 CSS 處理方案。