React.js快速入門 — (4)Component

Mackerel Chang
Mess up
Published in
7 min readFeb 3, 2020

Component — React.js最小組成,針對16.8版後的React.js所製作的新手入門上手文章

Photo modified from chewpeople (臺南市立美術館二館)

在上一篇文章:React.js快速入門 — (3)JSX,介紹了JSX的使用方式並且哪些坑應該避免。JSX就是協助用來負責建立Element的。Element跟Component差別又在哪裡呢?

在官方描述是說,Component是:

Component 可以讓你把 UI 切分為獨立並可重複使用的單位,並且每個單位可以抽出來獨立思考

Element則是:

來描述你的 UI 應該長成什麼樣子

註:UI指的是使用者介面,也就是網頁畫面呈現的樣子。

React Element

建立 React 應用程式最小的單位是 element。Element 是由 component 所「組成」的。

亦即Element由一個或以上的Component組成的,Component就是將很多功能做能重複使用的函式模組化,組成起來並且能夠輸出到網頁的叫做Element。

JSX 標籤的第一個部分決定 React element 的類型。

任何的React Element最上層節點只能有一個

//可以輸出
ReactDOM.render(
(<div>
<h1>Hello, world!</h1>
<h2>Brian</h2>
</div>),
document.getElementById('root')
);
//不能輸出
ReactDOM.render(
(<h1>Hello, world!</h1>
<h2>Brian</h2>),
document.getElementById('root')
);

順帶一提,若你期望要能實現上面”不能輸出”的東西,必須使用React Fragments。這份教學不會使用到,請安心繼續服用。

React Element & Component

Component原則

  1. Component就是基於Javascript的函式,呼叫Component可以使用 props 傳遞參數, props 的細節將在下一篇分析。只是在回傳的時候是用JSX或是React Element方式傳遞。
    例如: function Hello(props){return <H1>{props.sendData}</H1>;}
  2. 依照React.js規定,Component的函式命名的字首須為大寫字母,傳遞參數的時候是依照camelCase。例如: <Hello sendData="mynameishello"/>
  3. Component最高層通常都有一個名為App Component。例如:Create-React-App的 app.js 檔案綁到 index.js ,也像是(2)Overview章節提到的「會綁定最高層的Component」,只是 index.html 也寫成 index.js

Component有分成兩大種類 — Function形式Class形式,以及一個合成屬性 — Composition。

Function Component

用Function包覆想要 render 的內容。

function Welcome(props){
return <h1>Hello, {props.userName}</h1>;
}

最後要 render 的時候需要呼叫 reactDOM.render() 協助輸出到網頁上。

ReactDOM.render(
<Welcome userName="World"/>
document.getElementById('root')
);

(ES6) Class Component

用Class包覆所有需要的函式,包括 render 也寫在裡頭。它的存在是要配合 state 的儲存以及生命週期的處理, state 將在下一篇介紹。

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

宣告一個 class 然後繼承 React.Component 取得 Component 一些功能函式。 props 的部分必須要先在 constructor() 建構式使用 superReact.Component 綁定,呼叫class的時候constructor 就會自動啟動。

最後當有任何更新的時候都會自動呼叫 render() 執行。

不過自從 hook 的出現,React.js 也推薦開始少用 Class Component,因為 hook 已經協助包辦堪稱 Javascript 最大障礙:Class的 this 問題以及 state 生命週期的整合,這些都會在下一篇完整介紹。

Element接Element

在還沒有要 Render 之前,我們可以不斷組合Component成一個Element再給另一個Element接,最後再呈現到網頁上。

假設我們有三個檔案 Main.jsTodoHeader.jsTodoList.js 都在同一個資料夾。

TodoHeader.js :

const TodoHeader = ()=>(
<div>
<h1>TodoHeader</h1>
</div>
);
export default TodoHeader;

TodoList.js :

const TodoList = ()=>(
<div>
<h1>TodoList</h1>
</div>
);
export default TodoList;

Main.js 就將這兩個檔案做import,並且引用然後輸出到網頁:

import TodoHeader from './TodoHeader'
import TodoList from './TodoList'
ReactDOM.render(
(<div>
<TodoHeader/>
<TodoList/>
</div>),
document.getElementById('root')
);

如此一來就可以把Element跟Element連接在一起。

()=>() :是Arrow function,是 function(){return ();} 的簡寫

有關 importexportexport default 的跨檔案引入問題,可參考openhome.cc的介紹

Composition

有些 component 不會提早知道它們的 children 有些什麼。對於像是 SidebarDialog 這類通用的「box」component 特別常見。

在上一張有提到JSX的Children可傳遞下去給Component,我們在Component運用Children的內容稱之為Composition。

上層:

function WelcomeDialog() {
return (
<FancyBorder color="blue">
<h1 className="Dialog-title">
Welcome
</h1>
<p className="Dialog-message">
Thank you for visiting our spacecraft!
</p>

</FancyBorder>
);
}

下層:

function FancyBorder(props) {
return (
<div className={'FancyBorder FancyBorder-' + props.color}>
{props.children}
</div>
);
}

會將上層粗體字傳到 props.children 裡頭。

更多使用方式,請整系列觀看完後詳見官方文本

結語

此環節是React.js最重要的部分,因此著墨不少地方,把這裡慢慢消化再繼續前往下一篇:如何在Component儲存我要的資料。

喜歡的話可以給我一點掌聲唷!

上一篇:React.js快速入門 — (3)JSX
下一篇:React.js快速入門 — (5)Prop&State&Hook

--

--

Mackerel Chang
Mess up
Editor for

專攻於 Local Style Transfer 的碩士生。副業是接觸前端網頁。偶爾發發論文筆記與React.js心得。 https://www.linkedin.com/in/ching-yu-chang-270747195/