在 昨天的案例 中,我們注意到 react 似乎是把 html 寫進 js 裡面了,但其實那並不是 html ,它只是一種叫做 jsx 的語法糖,這一章節就是要跟大家說明 jsx 到底是什麼東西
語法糖:把原本複雜難以撰寫的語法,用一種更為簡潔的語法來包裝,但其實包裝前後底層的原理是一樣的,不去使用也不影響程式的開發,純粹是為了更好的開發者體驗,ES6 裡面的 class 就是一種語法糖。
我們前面也有說明過,要了解一個東西,看官方的文件是最好的方法,我們可以在 facebook 的 github page 找到官方對他的定義
JSX is an XML-like syntax extension to ECMAScript without any defined semantics.(jsx 是 ECMAScript 的一種很像 XML 的語法擴展,本身沒有任何的語意。)
我們會覺得 jsx 像 html,其實是因為 jsx 像 XML,XML 又和 HTML 長得非常相似,而前端工程師和 html 比較熟,所以才會有這種錯覺,至於為什麼 facebook 要將 jsx 創造出來呢?這件事情可以用簡單的一個範例來解釋 jsx 存在的價值。
如果有使用 jsx 的話,要創造一個 react element,我們可以這樣子寫
// 使用 jsx
const block = (
<div className='foo_class'>
<div className='bar_class'>bar</div>
<div className='bar_class'>bar</div>
<div className='bar_class'>bar</div>
</div>
);
在 javascript 裡面 class 是一個保留字,因此原本 html 的 class 屬性 ,在 jsx 裡面叫做 className
接著讓我們把 JSX 拿掉,讓 react 返璞歸真,使用本身的 api 來創建 react element
// 沒有使用 jsx
const block = React.createElement("div", {
className: "foo_class"
}, React.createElement("div", {
className: "bar_class"
}, "bar"), React.createElement("div", {
className: "bar_class"
}, "bar"), React.createElement("div", {
className: "bar_class"
}, "bar"));
react 本身並沒有強制規定一定要使用 jsx ,不過大家可以反覆比較一下,這兩者的差距,就能發現使用 jsx 能夠大大的增加程式碼的可讀性,所以就算沒有強制規定,官方依然推薦大家使用 jsx 來開發 react,不但增加開發上的速度,更能增進程式碼的可讀性。
蠻推薦剛學習的同學到 JSX live Editor 去玩玩看,不但能確認自己的語法是否是合格的語法,更能感受到 JSX 的魅力
JSX 本身並沒有語意,它是能夠自定義標籤名稱的
const foo = (<CustomTag></CustomTag>);
在沒有 children 的時候,可以直接關閉標籤
const foo = (<CustomTag/>);
它不僅能寫 className ,也可以傳遞自定義的資料
const foo = (
<CustomTag
myString="abc"
myNumber={123}
myBoolean={true}
myArray={[1, 2, 3]}
myObject={{ a: 123 }}
myFunction={() => {
console.log("hello world");
}}
/>
);
還可以使用 es6 的 … 語法來展開一個 object
const bar = {
myString:'abc',
myNumber:123,
myBoolean:true,
myArray:[1,2,3],
myObject:{foo:'bar'},
myFunction:()=>{console.log('hello world')}
}
//這個結果和上面那個範例的結果會是相同的
const foo = (<CustomTag {...bar}/>)
在 jsx 裡面到處都能發現花括弧的存在,花括弧裡面其實就是 javascript 的語法
//1.
const foo = (
<Time year={new Date().getFullYear()}/>
);
//2.
const foo = (
<Header>
{isLogin?<LoginButton/>:<LogoutButton/>}
</Header>
);
//3.
const foo = (
<Box>
{
someArray.map((item,i)=><Item text={item.text} key={item.id} />)
}
</Box>)
比較需要注意的是花括弧內一定要有 return 的值,因為就像剛剛說的,jsx 最後都會轉換成 React.createElement
,很多人會想在裡面這樣寫
<Header>
{
if(isLogin)
<LoginButton/>
else
<LogoutButton/>
}
</Header>
但是其實這麼寫是不對的,因為 jsx 在經過轉換後,我們會得到這樣子的結果
React.createElement(Header, null, if(isLogin)
<LoginButton/>
else
<LogoutButton/>);
這樣明顯不符合 js 的規範,所以在 react 中,我們通常會使用三元運算子的方式來實作它
<Header>
{
isLogin?<LoginButton/>:<LogoutButton/>
}
</Header>
若是真的比較喜歡 if else 的話,我們可以考慮使用 IIFE (立即執行函示) 來達成目的
<Header>
{
(()=>{
if(isLogin)
return <LoginButton/>
else
return <LogoutButton/>
})()
}
</Header>
今天介紹了使用 jsx 的好處和它的使用方法,這個算是要進入 react 世界的前哨戰,明天我們要正式開始跟 react 戰鬥了
依然建議各位同學要到 JSX live Editor 去自己試玩看看,絕對會有更深的收穫喔