iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 4
3
Modern Web

React 30天系列 第 4

Day 04-React的靈魂角色(Components)

前情提要:
昨天認識了JSX,知道它只是長得像html的javascript,在使用上很方便但要注意class要轉成className,for要轉成htmlFor...等

今天終於要講到靈魂角色components(元件)了。重要程度堪比烏蘇拉!但不是反派XD
https://media.giphy.com/media/mn827Gfu396RG/giphy.gif

什麼是Components?

先來看看官方解釋吧

React components are small, reusable pieces of code that return a React element to be rendered to the page.
出處:Glossary of React Terms-Components

React components是一個微小、可重複使用的程式碼片段,會回傳React element來渲染頁面。
好像有點抽象?我們把youtube搜尋頁截圖看看
https://ithelp.ithome.com.tw/upload/images/20181010/20111595Cv7gcAXq1x.png
區塊粗略來看中間紅色的列表,列表內的訂閱按鈕,左邊綠色的選單都是可重複使用的,當然還有其他林林總總的地方可以劃分,一個頁面就是由這些component們共同組成。

Components長什麼樣子?

Components擁有兩種不同型態,第一種是Function Components,也是最簡單的定義方式,沒錯,寫個function就對了。下面列出四種寫法,都可以達到相同的效果,相關的概念可參考:

// 函數聲明式
function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}
// 函數表達式
var Welcome = function() {
  return <h1>Hello, {props.name}</h1>;
}
// 箭頭函數(ES6寫法)
const Welcome = (props) => {
  return <h1>Hello, {props.name}</h1>;
}
// 箭頭函數 + 解構(ES6寫法)
const Welcome = ({name}) => <h1>Hello, {name}</h1>;

另一種則是Class Components

class Welcome extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}

Class Components比Function Component多了一些額外的功能,這個我們明天再來講。
不論是哪種component都可以傳入props,props的功能可以幫助我們將所需的資料傳給component使用。
而props在JSX內又要怎麼用呢?根據官方說法

You can pass any JavaScript expression as a prop, by surrounding it with {}.
出處:Props in JSX
JavaScript(運算式)是任何一段可以取得value(值)的程式碼,在大括號內放的任何運算式都可以作為props傳入component,舉凡variable, array, object, string, 三元運算子或執行function return的值都可以合格使用。

那要怎麼使用呢?我們直接來實作吧,先做個按鈕component試水溫吧!

試做一個Button Component

需求

  1. 按鈕為獨立的component
  2. 按鈕文字可以透過props傳入

找個趁手的編輯器(我使用VS code),把第二天建好的開發環境打開
https://ithelp.ithome.com.tw/upload/images/20181011/20111595U4qssmJPaf.png
目前應該會是這模樣。
我們先在index.js裡增加一個名叫Button的component

注意
所有componet的名稱都應該為英文大寫開頭,小寫React會誤會是DOM tags,導致不預期的錯誤。

const Button = ({text}) => {
  return (
    <button>{text}</button>
  )
}

我們完成了!接著把我們的按鈕塞到App內,順便把按鈕文字透過傳給Button用吧

const App = () => {
  return (
    <div>
      Hello World!
      <Button text="按鈕按鈕"/>
    </div>
  );
};

所以目前index.js應該會長這樣

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

const Button = ({text}) => {
  return (
    <button>{text}</button>
  )
}

const App = () => {
  return (
    <div>
      Hello World!
      <Button text="按鈕按鈕"/>
    </div>
  );
};

ReactDOM.render(<App/>, document.getElementById('app'));

打開terminal,執行yarn startnpm start
我都用yarn,所以之後就不另外提npm囉,操作基本都一樣,就不多寫傷大家眼了。

yarn start

打開瀏覽器,在localhost:8080我們可以看到頁面目前長這樣
https://ithelp.ithome.com.tw/upload/images/20181011/20111595k0fzYnHpWB.png
既然說component是可以重複使用的,那我們來試試把按鈕增量吧!

// ...
const App = () => {
  return (
    <div>
      Hello World!
      <Button text="按鈕按鈕"/>
      <Button text="按鈕排序二"/>
      <Button text="按鈕排序三"/>
      <Button text="按鈕排序四"/>
    </div>
  );
};
// ...

https://ithelp.ithome.com.tw/upload/images/20181011/20111595vmPOO23lCS.png
太好了可以正常運作。
不過隨著component越來越多全部放在index.js會眼花撩亂吧!
我們新增一個src資料夾在裡面建立components資料夾把Button component單獨抽離吧!
在terminal上輸入以下指令建立資料夾

mkdir -p src/components

接著在components內新增button.js,並把index.js的Button相關程式碼搬進去,注意要import React和export Button喔!在button.js的程式碼會長的像這樣
button.js
https://ithelp.ithome.com.tw/upload/images/20181011/20111595DKpZmhgAvj.png
index.js
https://ithelp.ithome.com.tw/upload/images/20181011/20111595HivU2s0mfh.png
一樣可以正常運作!
關於import和export: 屬於ES6的範疇,他們可以匯入和匯出module,我們這邊的用法即是把Button獨立成一個module export出去,然後在index.js使用import進來。更詳細的內容可參考importexport


總結今日:

  • React components是一個微小、可重複使用的程式碼片段
  • Components擁有兩種不同型態,分別為
    • Function Components
    • Class Components
  • props的功能為幫助我們將所需的資料傳給component使用
  • 我可以傳入任何JavaScript expression作為props藉由在外面包裹一層大括號{}
  • 所有componet的名稱都應該為英文大寫開頭
  • 通常一個component會是抽出成一個獨立module使用,使用import & export匯入匯出

講到component沒講到props好像就少了很多東西可以講,今天用到的component都屬於Function Components,明天我們再帶入到Class Components吧!
有任何錯誤請多指正,新手任務未完成不能回文真的蠻尷尬的,哈哈......


上一篇
Day 03-其實我只是披著html的javascript(JSX)
下一篇
Day 05-靈魂角色的家庭成員(Props & State)
系列文
React 30天30

尚未有邦友留言

立即登入留言