本篇是 React 這套 JavaScript 函式庫的入門教學,介紹如何使用 React 開發互動式的網頁應用程式。

React 是 facebook 官方所維護的開放原始碼 JavaScript 函式庫,可以降低互動式網頁應用程式開發難度,自動處理各種複雜 UI 組件與資料間的連動關係,改善應用程式執行效能。

學習用 React 範本

對於初學者說,建議可以使用以下這份 React 的學習專用範本,直接將這段 HTML 原始碼貼在自己的編輯器中,儲存成 HTML 網頁檔,以瀏覽器打開後即可看到 React 的 hello world 程式執行的結果。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>Hello World</title>

    <!-- 引入 React -->
    <script src="https://unpkg.com/react@16/umd/react.development.js"></script>
    <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>

    <!-- 引入 Babel -->
    <script src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"></script>

  </head>
  <body>
    <div id="root"></div>
    <script type="text/babel">

      // React 的 JSX 程式碼
      ReactDOM.render(
        <h1>Hello, world!</h1>,
        document.getElementById('root')
      );

    </script>
  </body>
</html>

在接下來的教學內容都可以使用這個 HTML 網頁檔來執行。

React 標準開發環境

使用單一 HTML 範本檔來學習 React 是很方便的作法,但這種方式的程式執行效率較低,不適合用於正式的專案。

若要開發標準的 React 專案,建議使用 create-react-app 這個工具來建立新專案,第一次使用之前請先安裝:

# 安裝 create-react-app
npm install -g create-react-app

接著建立新 React 專案:

# 建立新 React 專案
create-react-app my-app

若使用 npm 5.2 以上的版本,可以改用 npx 直接呼叫 create-react-app 來建立新專案:

# 改用 npx(免安裝 create-react-app)
npx create-react-app my-app

建立好新的 React 專案之後,進入專案目錄,啟動開發用伺服器,即可開始撰寫 React 的程式:

# 進入專案目錄
cd my-app

# 啟動開發用伺服器
npm start

若要產生可以佈署出去的專案成品,可以執行:

# 建置專案
npm run build

其餘更詳細的專案操作,請直接參考 React 的官方文件

JSX 簡介

JSX 是一種 JavaScript 的擴充語言,加入了一些 HTML 標籤的語法,下面這一行就是 JSX 典型的程式碼:

const element = <h1>Hello, world!</h1>;

在多數的應用程式中,UI 都會與資料、事件或其他 UI 有關係,因此 React 架構在設計上就將 HTML 標籤與 JavaScript 控制邏輯合併,以 JSX 來描述 UI 的外觀與運作邏輯,打造出 React 的 UI 組件(components),再用這些 UI 組件堆疊出個應用程式。

開發 React 應用程式時,不一定要使用 JSX 語言,不過通常使用 JSX 會比較方便。

JSX 內嵌 JavaScript

我們可以在 JSX 中以大括號內嵌任何的 JavaScript 運算,例如:

// 普通的 JavaScript
function formatName(user) {
  return user.firstName + ' ' + user.lastName;
}
const user = {
  firstName: 'Harper',
  lastName: 'Perez'
};

// JSX 內嵌 JavaScript
const element = (
  <h1>
    Hello, {formatName(user)}!
  </h1>
);

// 普通的 JavaScript
ReactDOM.render(
  element,
  document.getElementById('root')
);

在這裡我們將 JSX 內的標籤分成多行來寫(也可以合併為一行),這種狀況建議在頭尾加上小括號,避免不小心造成解析錯誤。

JSX 與 JavaScript

事實上 JSX 的程式碼在經過編譯之後,會轉為普通的 JavaScript 函數來執行,產生特別的 JavaScript 物件,所以 JSX 可以放在判斷式、迴圈中,也可以指定給 JavaScript 的變數、作為函數的參數或傳回值等:

// JSX 與 JavaScript 混合使用
function getGreeting(user) {
  if (user) {
    return <h1>Hello, {formatName(user)}!</h1>;
  }
  return <h1>Hello, Stranger.</h1>;
}

JSX 指定屬性值

JSX 中的網頁標籤若要指定屬性值,語法跟普通的 HTML 語法類似:

// JSX 指定屬性值
const element = <div tabIndex="0"></div>;

若要以內嵌的 JavaScript 來指定屬性值,則使用大括號將 JavaScript 的運算式包起來放進去:

// JSX 內嵌 JavaScript 指定屬性值
const element = <img src={user.avatarUrl}></img>;

這裡要注意一點:使用大括號時不可以加上引號。

JSX 標籤與子節點

JSX 跟 XML 的規則類似,若遇到非成對的標籤,最後要以 /> 結尾。

// 單一標籤
const element = <img src={user.avatarUrl} />;

JSX 可以像普通網頁一樣,包含多個子節點:

// 標籤可含有子節點
const element = (
  <div>
    <h1>Hello!</h1>
    <h2>Good to see you here.</h2>
  </div>
);

預防駭客攻擊

JSX 在內嵌資料時,會自動跳脫(escape)任何特別的字元,所以不用擔心隱碼攻擊(injection attacks):

// 使用者輸入資料
const title = response.potentiallyMaliciousInput;

// 安全無虞
const element = <h1>{title}</h1>;

JSX 代表物件

JSX 經過 Babel 編譯之後,會轉換為 React.createElement() 這個 JavaScript 的函數,也就是說以下兩段程式碼的效果是相同的:

// 原始 JSX
const element = (
  <h1 className="greeting">
    Hello, world!
  </h1>
);

// JSX 編譯後的 JavaScript
const element = React.createElement(
  'h1',
  {className: 'greeting'},
  'Hello, world!'
);

React.createElement() 會進行一些檢查,協助開發者減少錯誤發生的機會,基本上它產生的物件會類似這樣:

// 簡化的 JSX 物件結構
const element = {
  type: 'h1',
  props: {
    className: 'greeting',
    children: 'Hello, world'
  }
};

這就是典型的 React 元素,React 就是靠著這些資訊來建立與更新 DOM 的。