iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 12
0
Modern Web

使用 React 製作簡易專案管理網站:從基礎到實戰系列 第 12

[Day 12] React 保衛戰 - 集合!建立「元件」軍隊

  • 分享至 

  • xImage
  •  

讀者進入以下網址:https://codesandbox.io/s/new,就能進到由 CodeSandbox 提供的線上開發環境以及使用 create-react-app 指令建立好的 React 專案來進行練習

「元件」軍隊 - 由「元素」士兵組成

基本的元件(component)是由一個或多個元素所組成,我們可以將重複出現或是負責某個功能的一組元素包裝成元件,所有元件會形成一棵元件樹,元件樹由一個根元件往下長出其他的元件,而一個元件內可能又包含其他一個或多個元件,形成階層關係,外層的元件稱為父元件,內層的元件稱為子元件,基本上每個元件是互相獨立的(但父元件可以透過 props 來傳遞資料給子元件,這一觀念會在下一篇文章介紹),下面我們透過範例來講解。

首先進入 https://codesandbox.io/s/new,將 index.js 這支檔案裡面的 App 函式裡面的內容改為:

function App() {
  return (
    <div>
      <h1>React</h1>
      <div>
        <p>React 具有以下特性:</p>
        <ul>
          <li>Virtual DOM 的機制</li>
          <li>元件化的開發</li>
        </ul>
      </div>
      <div>
        <p>三大前端框架:</p>
        <ul>
          <li>React</li>
          <li>Vue</li>
          <li>Angular</li>
        </ul>
      </div>
    </div>
  );
}

我們可以觀察到其中以下這兩個部分的結構很類似,都同樣具有一個文字敘述和一組項目清單:

<div>
  <p>React 具有以下特性:</p>
  <ul>
    <li>Virtual DOM 的機制</li>
    <li>元件化的開發</li>
  </ul>
</div>
<div>
  <p>三大前端框架:</p>
  <ul>
    <li>React</li>
    <li>Vue</li>
    <li>Angular</li>
  </ul>
</div>

因此我們傾向於將它們包裝建立成元件,這邊用樹狀圖來幫助讀者們理解:

https://ithelp.ithome.com.tw/upload/images/20190927/20104727iFvq51eQFd.png

建立「元件」軍隊 - 使用函式來建立元件

元件可以透過宣告函式的方式來建立,因此又可稱為函式元件,函式名稱就是元件的名稱,而函式的返回值就是被包裝的元素,我們的目標是將上面第一個部分包裝成 Block1 元件,第二個部分則包裝成 Block2 元件。

首先在 App 函式上方宣告一個名稱為 Block1 的函式,函式返回值就是第一個部分的元素:

function Block1() {
  return (
    <div>
      <p>React 具有以下特性:</p>
      <ul>
        <li>Virtual DOM 的機制</li>
        <li>元件化的開發</li>
      </ul>
    </div>
  )
}

接著再宣告一個名稱為 Block2 的函式,函式返回值就是第二個部分的元素:

function Block2() {
  return (
    <div>
      <p>三大前端框架:</p>
      <ul>
        <li>React</li>
        <li>Vue</li>
        <li>Angular</li>
      </ul>
    </div>
  )
}

「元件」軍隊上戰場 - 使用建立好的元件

建立好的元件在 JSX 語法中可以透過類似標籤的方式來使用,方式如下:

<元件名稱></元件名稱>

而在之前介紹 JSX的文章中有提到:

沒有內容的 JSX 元素可以自閉

同樣的規則也適用於元件,因此也可以這樣寫:

<元件名稱 />

接續前一段,我們已經建立好 Block1 和 Block2 元件,現在可以用來取代掉 App 函式中的部分元素:

function App() {
  return (
    <div>
      <h1>React</h1>
      <Block1 />
      <Block2 />
    </div>
  );
}

是不是簡潔許多了呢?


這邊要特別注意:由於元件的使用方式是透過標籤的型式,所以元件名稱必須遵守大駝峰式命名法(upper camel case),避免使用該元件時被當作是一般的元素。

// 沒有遵守大駝峰式命名法(upper camel case)
function button() {
  return ...
}

// 使用該元件時,被當作是一般的按鈕元素
<button />

若我們進一步觀察 Block1 和 Block2 裡面的元素結構,會再發現以下這兩個部分的結構也很類似:

<ul>
  <li>Virtual DOM 的機制</li>
  <li>元件化的開發</li>
</ul>
<ul>
  <li>React</li>
  <li>Vue</li>
  <li>Angular</li>
</ul>

讀者們可以嘗試再將它們元件化為 List1 和 List2 當作練習,在此就不贅述元件化的過程,附上 index.js 檔案完整的程式碼:

import React from "react";
import ReactDOM from "react-dom";

import "./styles.css";

function List1() {
  return (
    <ul>
      <li>Virtual DOM 的機制</li>
      <li>元件化的開發</li>
    </ul>
  );
}

function List2() {
  return (
    <ul>
      <li>React</li>
      <li>Vue</li>
      <li>Angular</li>
    </ul>
  );
}

function Block1() {
  return (
    <div>
      <p>React 具有以下特性:</p>
      <List1 />
    </div>
  );
}

function Block2() {
  return (
    <div>
      <p>三大前端框架</p>
      <List2 />
    </div>
  );
}

function App() {
  return (
    <div>
      <h1>React</h1>
      <Block1 />
      <Block2 />
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

以及樹狀示意圖:

https://ithelp.ithome.com.tw/upload/images/20190927/20104727pyyPZPHn0j.png

「元件」軍隊的指揮總部 - 元件樹的根元件

在上述範例中,我們自行建立了 Block1、Block2、List1、List2 四個元件,其中 List1 和 List2 分別為 Block1 和 Block2 的子元件,反過來說,Block1 和 Block2 則分別為List1 和 List2 的父元件,那 Block1 和 Block2 的父元件又是誰呢?我們從程式碼中可以看到,Block1 和 Block2 都被使用在 App 函式中,因此我們可以推斷 Block1 和 Block2 的父元件就是 App 元件。

那 App 元件的父元件又是誰呢?答案是:App 沒有父元件,因為 App 並沒有被使用在其他的元件中,代表它的外層已經沒有其他元件,因此 App 就是整個元件樹的根元件。

https://ithelp.ithome.com.tw/upload/images/20190928/20104727pWDrkLydyA.png

那在之前介紹 JSX的文章中有提到:

JSX 語法會先經過 babel 轉譯成 JavaScript 程式碼,再經過瀏覽器執行,由 React 轉換為存在記憶體中的 virtual DOM,並且產生建立實際的 DOM

整棵元件樹便是由 JSX 語法寫成的,因此這些元件會由 React 轉換為存在記憶體中的 virtual DOM,那又是如何產生建立實際的 DOM 呢?程式碼中的這兩行扮演關鍵的腳色:

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

第一行程式碼中,先取得 id 為 root 的 div 元素,然後在第二行程式碼中,呼叫 ReactDOM.render 將 App 根元件掛載到該 div 元素,如此便會從根元件開始一層一層的將所有元件或元素「渲染」(render)到畫面上,而所謂「渲染」其實就是將 virtual DOM 轉換為實際的 DOM 的過程,至於 id 為 root 的 div 元素在哪?我們可以到專案中 public 資料夾底下 index.html 檔案的內容中找到。

結語

希望讀者們看完本篇文章,能夠對元件有基本的認識並且學會如何建立元件,下一篇文章我們將更進一步探討元件進階用法以及如何使用 props 來發揮元件的重複使用性。

參考資料:

  1. ReactDOM – React - https://reactjs.org/docs/react-dom.html#render

上一篇
[Day 11] React 保衛戰 - 注意!JSX 元素屬性是 HTML 元素屬性的變形
下一篇
[Day 13] React 保衛戰 - 滴答滴答!元件軍隊收到「props」電報
系列文
使用 React 製作簡易專案管理網站:從基礎到實戰30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言