回文章列表

Modern React 新手補給站(2)-JSX

新手補給站(2)-JSX

昨天的案例 中,我們注意到 react 似乎是把 html 寫進 js 裡面了,但其實那並不是 html ,它只是一種叫做 jsx 的語法糖,這一章節就是要跟大家說明 jsx 到底是什麼東西

語法糖:把原本複雜難以撰寫的語法,用一種更為簡潔的語法來包裝,但其實包裝前後底層的原理是一樣的,不去使用也不影響程式的開發,純粹是為了更好的開發者體驗,ES6 裡面的 class 就是一種語法糖。

JSX是什麼?為什麼要使用它

我們前面也有說明過,要了解一個東西,看官方的文件是最好的方法,我們可以在 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 常用的語法教學

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 去自己試玩看看,絕對會有更深的收穫喔

發表於 Aug 2, 2019

You cannot improve your past, but you can improve your future.Ryan Chu on Github