一看就懂的 JSX 簡明入門教學指南


Posted by KD Chang on 2016-04-21

一看就懂的 JSX 簡明入門教學指南

前言

根據 React 官方定義,React 是一個構建使用者介面的 JavaScritp Library。以 MVC 模式來說,ReactJS 主要是負責 View 的部份。過去一段時間,我們被灌輸了許多前端分離的觀念,在前端三兄弟中(或三姊妹、三劍客):HTML 掌管內容結構、CSS 負責外觀樣式,JavaScript 主管邏輯互動,千萬不要混在一塊。然而,在 React 世界裡,所有事物都是 以 Component 為基礎,將同一個 Compoent 相關的程式和資源都放在一起,而在撰寫 React Component 時我們通常會使用 JSX 的方式來提升程式撰寫效率。事實上,JSX 並非一種全新的語言,而是一種語法糖(Syntatic Sugar),一種語法類似 XML 的 ECMAScript 語法擴充。在 JSX 中 HTML 和組建這些元素標籤的程式碼有緊密的關係。因此你可能要熟悉一下以 Component 為單位的思考方式(本文主要使用 ES6 語法)。

此外,React 和 JSX 的思維在於善用 JavaScript 的強大能力,放棄蹩腳的模版語言,這和 Angular 強化 HTML 的理念也有所不同。當然 JSX 並非強制使用,你也可以選擇不用,因為最終 JSX 的內容會轉化成 JavaScript(瀏覽器只看的懂 JavaScript)。不過等你閱讀完接下來的內容,你或許會開始發現 JSX 的好,認真考慮使用 JSX 的語法。

一、使用 JSX 的好處

1. 提供更加語意化且易懂的標籤

由於 JSX 類似 XML 的語法,讓一些非開發人員也更容易看懂,且能精確定義包含屬性的樹狀結構。一般來說我們想做一個回饋表單,使用 HTML 寫法通常會長這樣:

<form class="messageBox">
  <textarea></teextarea>
  <button type="submit"></button>
</from>

使用 JSX,就像 XML 語法結構一樣可以自行定義標籤且有開始和關閉,容易理解:

<MessageBox />

React 思路認為使用 Component 比起模版(Template)和顯示邏輯(Display Logic)更能實現關注點分離的概念,而搭配 JSX 可以實現聲明式 Declarative(注重 what to),而非命令式 Imperative(注重 how to)的程式撰寫方式:

Facebook 上面按讚功能

以 Facebook 上面按讚功能來說,若是命令式 Imperative 寫法大約會是長這樣:


if(userLikes()) {
  if(!hasBlueLike()) {
    removeGrayLike();
    addBlueLike();
  }
} else {
  if(hasBlueLike()) {
    removeBlueLike();
    addGrayLike();
  }
}

若是聲明式 Declarative 則是會長這樣:

if(this.state.liked) {
  return (<BlueLike />);
} else {
  return (<GrayLike />);
}

看完上述說明是不是感覺 React 結合 JSX 的寫法更易讀易懂?事實上,當 Component 組成越來越複雜時,若使用 JSX 將可以讓整個結構更加直觀,可讀性較高。

2. 更加簡潔

雖然最終 JSX 會轉換成 JavaScript,但使用 JSX 可以讓程式看起來更加簡潔,以下為使用 JSX 和不使用 JSX 的範例:

<a href="https://facebook.github.io/react/">Hello!</a>

不使用 JSX 的情況(記得我們說過 JSX 是選用的):

// React.createElement(元件/HTML標籤, 元件屬性,以物件表示, 子元件)
React.createElement('a', {href: 'https://facebook.github.io/react/'}, 'Hello!')

3. 結合原生 JavaScript 語法

JSX 並非一種全新的語言,而是一種語法糖(Syntatic Sugar),一種語法類似 XML 的 ECMAScript 語法擴充,所以並沒有改變 JavaScript 語意。透過結合 JavaScript ,可以釋放 JavaScript 語言本身能力。下面例子就是運用 map 方法和 Arrow function,輕易把 result 值迭代出來,產生無序清單(ul)的內容,不用再使用蹩腳的模版語言:

// const 為常數
const lists = ['JavaScript', 'Java', 'Node', 'Python'];

class HelloMessage extends React.Compoent {
  render() {
    return (
    <ul>
      {lists.map((result) => {
        return (<li>{result}</li>);
      })}
    </ul>);
  }
}

二、JSX 用法摘要

1. 環境設定與使用方式

初步了解為何要使用 JSX 後,我們來聊聊 JSX 的用法。一般而言 JSX 通常有兩種使用方式:

  1. 使用 browserifywebpackCommonJS bundler 並整合 babel 預處理
  2. 於瀏覽器端做解析

在這邊簡單起見,我們先使用第二種方式,先讓大家專注熟悉 JSX 語法使用,等到後面章節再教大家使用 bundler 的方式去做解析(可以試著把下面的原始碼貼到 JSbin 的 HTML 看結果):

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>Hello React!</title>
    <!-- 請先於 index.html 中引入 react.js, react-dom.js 和 babel-core 的 browser.min.js -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.0.1/react.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.0.1/react-dom.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.23/browser.min.js"></script>
  </head>
  <body>
    <div id="example"></div>
    <script type="text/babel">
      // 程式碼寫在這邊!
      ReactDOM.render(
        <h1>Hello, world!</h1>,
        document.getElementById('example')
      );
    </script>
  </body>
</html>

一般載入 JSX 方式有:

  • 內嵌
<script type="text/babel">
  ReactDOM.render(
    <h1>Hello, world!</h1>,
    document.getElementById('example')
  );
</script>
  • 從外部引入

<script type="text/jsx" src="main.jsx"></script>

2. 標籤用法

JSX 標籤非常類似 XML ,可以直接書寫。一般 Component 命名首字大寫,HTML Tags 小寫。以下是一個建立 Component 的 class:

class HelloMessage extends React.Compoent {
  render() {
    return (
      <div>
        <p>Hello React!</p>
        <MessageList />
      </div>
    );
  }
}

3. 轉換成 JavaScript

JSX 最終會轉換成瀏覽器可以讀取的 JavaScript,以下為其規則:

React.createElement(
  string/ReactClass, // 表示 HTML 元素或是 React Component
  [object props], // 屬性值,用物件表示
  [children] // 接下來參數皆為元素子元素
)

解析前(特別注意在 JSX 中使用 JavaScript 表達式時使用 {} 括起,如下方範例的 text,裡面對應的是變數。若需希望放置一般文字,請加上 ''):

var text = 'Hello React';
<h1>{text}</h1>
<h1>{'text'}</h1>

解析完後:

var text = 'Hello React';
React.createElement("h1", null, "Hello React!");

另外要特別要注意的是由於 JSX 最終會轉成 JavaScript 且每一個 JSX 節點都對應到一個 JavaScript 函數,所以在 Component 的 render 方法中只能回傳一個根節點(Root Nodes)。例如:若有多個 <div>render 請在外面包一個 Component 或 <div><span> 元素。

4. 註解

由於 JSX 最終會編譯成 JavaScript,註解也一樣使用 ///**/ 當做註解方式:

// 單行註解

/*
  多行註解
*/

var content = (
  <List>
      {/* 若是在子元件註解要加 {}  */}
      <Item
        /* 多行
           註解
           喔 */
        name={window.isLoggedIn ? window.name : ''} // 單行註解
      />
  </List>
);

5. 屬性

在 HTML 中,我們可以透過標籤上的屬性來改變標籤外觀樣式,在 JSX 中也可以,但要注意 classfor 由於為 JavaScript 保留關鍵字用法,因此在 JSX 中使用 classNamehtmlFor 替代。

class HelloMessage extends React.Compoent {
  render() {
    return (
      <div className="message">
        <p>Hello React!</p>
      </div>
    );
  }
}

Boolean 屬性

在 JSX 中預設只有屬性名稱但沒設值為 true,例如以下第一個 input 標籤 disabled 雖然沒設值,但結果和下面的 input 為相同:

<input type="button" disabled />;
<input type="button" disabled={true} />;

反之,若是沒有屬性,則預設預設為 false

<input type="button" />;
<input type="button" disabled={false} />;

6. 擴展屬性

在 ES6 中使用 ... 是迭代物件的意思,可以把所有物件對應的值迭代出來設定屬性,但要注意後面設定的屬性會蓋掉前面相同屬性:

var props = {
  style: "width:20px",
  className: "main",
  value: "yo",  
}

<HelloMessage  {...props} value="yo" />

// 等於以下
React.createElement("h1", React._spread({}, props, {value: "yo"}), "Hello React!");

7. 自定義屬性

若是希望使用自定義屬性,可以使用 data-

<HelloMessage data-attr="xd" />

8. 顯示 HTML

通常為了避免資訊安全問題,我們會過濾掉 HTML,若需要顯示的話可以使用:

<div>{{_html: '<h1>Hello World!!</h1>'}}</div>

9. 樣式使用

在 JSX 中使用外觀樣式方法如下,第一個 {} 是 JSX 語法,第二個為 JavaScript 物件。與一般屬性值用 - 分隔不同,為駝峰式命名寫法:

<HelloMessage style={{ color: '#FFFFFF', fontSize: '30px'}} />

10. 事件處理

事件處理為前端開發的重頭戲,在 JSX 中透過 inline 事件的綁定來監聽並處理事件(注意也是駝峰式寫法):

<HelloMessage onClick={this.onBtn} />

總結

以上就是 JSX 簡明入門教學,希望透過以上介紹,讓讀者了解在 React 中為何要使用 JSX,以及 JSX 基本概念和用法。最後為大家複習一下:在 React 世界裡,所有事物都是以 Component 為基礎,通常會將同一個 Compoent 相關的程式和資源都放在一起,而在撰寫 React Component 時我們常會使用 JSX 的方式來提升程式撰寫效率。JSX 是一種語法類似 XML 的 ECMAScript 語法擴充,可以善用 JavaScript 的強大能力,放棄蹩腳的模版語言。當然 JSX 並非強制使用,你也可以選擇不用,因為最終 JSX 的內容會轉化成 JavaScript。當相信閱讀完上述的內容後,你會開始認真考慮使用 JSX 的語法。

延伸閱讀

  1. Imperative programming or declarative programming
  2. JSX in Depth
  3. 從零開始學 React(ReactJS 101)

(image via adweek, codecondo)

關於作者:
@kdchang 文藝型開發者,夢想是做出人們想用的產品和辦一所心目中理想的學校。A Starter & Maker. JavaScript, Python & Arduino/Android lover.:)


#React #React Native #ES5 #ES6 #ES7 #javascript #ECMAScript2015 #Webpack #JSX









Related Posts

[筆記] React 隨手記 (按下按鈕切換兩個css動畫功能)

[筆記] React 隨手記 (按下按鈕切換兩個css動畫功能)

sigfox開啟全球一個網的物聯網世界

sigfox開啟全球一個網的物聯網世界

AI輔導室|快速完成波浪線條

AI輔導室|快速完成波浪線條




Newsletter




Comments