iT邦幫忙

2022 iThome 鐵人賽

DAY 7
0
Modern Web

跳脫MVC,Laravel + React 建立電商網站系列 第 7

Day 7 React Element、Component and Prop

  • 分享至 

  • xImage
  •  

不知不覺就進展到第七天了,今天的目標是透過官方文件來理解React最基本的概念。
官方文件把這裡的東西拆成兩篇文章來講,但我覺得要一次讀完比較容易理解。

Element

基本上官方文件寫得很詳細,我覺得關於element就總括一句話:
https://ithelp.ithome.com.tw/upload/images/20220911/20145703GjcUQfJv6S.png

官方文件寫到:
Unlike browser DOM elements, React elements are plain objects, and are cheap to create. React DOM takes care of updating the DOM to match the React elements.
這裡的重點就一句話:React 的 element是一個純的Object。


【小補充】
這裡我想講一下,關於element 是指在畫面上看到的html 標籤,例如:div、p
那這些element並不是一個"純"object嗎?
還真的不是,每個element的object會有不同的屬性及方法,基本的屬性有:children、childrenNodes...之類的,所有html元素都有繼承來自 element Object 的屬性及方法。
詳細可以參考w3school的說明
至於Dom,DOM 的全文是document object model,中文是文件物件模型。
使用dom能夠操作html的元素(每個tag),如果JavaScript沒有DOM模型,則與其他程式語言並無不同。
透過dom模型操作html的元素(或變更元素中的屬性),都能夠使網頁與使用者的互動增加。


官方在element的地方有標註一個小說明:
大家可能會將element與Component搞混,但兩者並不相同,Component 是由 element 所「組成」的。

如果我們要在畫面上顯示element,會將需要顯示的元素render到dom之中,這裡直接拿官方的範例:

const root = ReactDOM.createRoot( 
  document.getElementById('root') 
); 
const element = <h1>Hello, world</h1>; 
root.render(element);

React Element是不可改變的,當我們創造了一個element,並不能夠再去改變他的屬性,因為這個React element代表某個時間點的畫面
官方在文件中也有提供如何更新element的資料,這裡來解讀一下:

const root = ReactDOM.createRoot( 
  document.getElementById('root') 
); 
function tick() { 
  const element = ( 
    <div> 
      <h1>Hello, world!</h1> 
      <h2>It is {new Date().toLocaleTimeString()}.</h2> 
    </div> 
  ); 
  root.render(element); 
} 
setInterval(tick, 1000);

首先,root 就是一個ReactDom
接著有一個tick的function,在function 之中寫好element,並將element reder回Dom之中,最後每一秒鐘(1000毫秒)跑一次tuck function

const 在JS之中代表常數,常數指的是不可重複宣告、不可重複給值的
https://ithelp.ithome.com.tw/upload/images/20220911/201457037E0eqWX9VX.png

那為什麼用呼叫的方式就沒有報錯呢?
這主要原因是因為 "const" 本身是有function scope的,因此每次宣告的生命週期只在當下的那個function之中

https://ithelp.ithome.com.tw/upload/images/20220911/20145703Q2SUqpYbW7.png
https://ithelp.ithome.com.tw/upload/images/20220911/201457031IuILhFm80.png

所以在react官方範例之中,透過scope的特性來更新element的內容,最後每次更新都render到DOM之中來達到我們要更新element的目的。

React DOM 會將 element 和它的 children 與先前的狀態做比較,並且只更新必要的 DOM 達到理想的狀態。
(ps.這句話是來自於官方文件,我覺得沒有什麼好解釋的就複製貼上XD

Components and Props

在官方文件中,元件(Components)跟屬性(Props)是在同一個章節介紹,因此我這裡也一倂介紹。
一開始官方給Components的定義是:
概念上來說,component 就像是 JavaScript 的 function,它接收任意的參數(稱之為「props」)並且回傳描述畫面的 React element。
簡單來說,Component就是"類"function的概念,接收的參數不叫parameter叫做props,這個類function 會回傳element。
官方的範例給出兩種宣告元件的方式:

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

這兩種方式都是可行的。
ps.關於js的class,我在Day4的時候有做過小補充,忘記的小夥伴可以回去看看,順邊幫我按個讚。
官方文件在這裡有埋下一個伏筆:Function 和 Class component 兩者都擁有額外的特性

官方的範例看起來沒甚麼難度,我們把柬埔寨專案拿出來加一些東西XD
因為我懶得排版了,我直接在left的地方加個comment資料
我們直接在left.js之中修改

import React from "react"; 
const Left = () => { 
    let slogan = ["月薪3000美金,包吃包住","工作輕鬆 - 辨公室客服","每三個月一張返鄉機票","成就自我價值"]; 
    let comments = [ 
        { name: "王大嗨" , age: "28" , comment: "我沒想到我可以這麼年輕就挑戰副理職位,年薪上看兩百萬" }, 
        { name: "江超人" , age: "26" , comment: "謝謝你,柬埔人,我的超人" }, 
        { name: "連載中" , age: "32" , comment: "謝謝公司願意給我這個機會來挑戰自己" }, 
        { name: "王曉華" , age: "42" , comment: "沒想到二度就業婦女都會有這麼好的就業機會" } 
    ]; 
    return ( 
        <div> 
            <ol> 
                { 
                slogan.map( value => { 
                        return <li key={value.toString()}>{value}</li>; 
                })   
                } 
            </ol> 
            <hr style={{width:"90%"}}/> 
            { 
                comments.map( value => { 
                    return <Comment name={value.name} age={value.age} comment={value.comment} key={value.toString()}/> 
                }) 
            } 
        </div> 
         
    ); 
} 
function Comment({name , age , comment}){ 
    return <div style={{width:"100%"}}> 
        <p style={{width:"100%" , marginLeft:"3rem"}}>姓名:{name}  年齡:{age}</p> 
        <p style={{width:"100%" , marginLeft:"3rem"}}>工作感想:{comment}</p> 
        <hr style={{width:"90%"}}/> 
    </div>; 
} 
export default Left;

https://ithelp.ithome.com.tw/upload/images/20220911/20145703RqKYNgTKPK.png

一開始我們創建了一個 名稱叫做 comment的array,array中4個object
接下來我們寫一個function ,命名就是component的名稱,接著我們設定這個function要接收三個props
(這裡我跟官方範例的做法比較不一樣,稍後會解釋),最後在原本的return 之中加入呼叫component的語法:
<ComponentName /> 並將需要帶進去的參數逐一填寫,即可。

如果採用官方範例,那我們剛剛建立comment component要改成如下:

function Comment(props){
    return <p>{props.name}</p>;
}

這兩個做法差在哪裡?
主要是 在React之中預設 Component接收到的參數 是"一個props"
當我們在呼叫 Component時,會帶入多個參數。
這個時候Components 的props是一個object
因此如果在接收的地方只有寫props,那麼要取的參數就要寫成props.xxx

那我們把props改成一個大括號加入properties的名稱,這時候其實React 幫我們偷偷執行了這個過程:

let {name , age , comment } = props;

這個東西叫做解構(Destruct)
如果我們從物件中拿資料時,一個一個得從物件拿出來,整體非常耗時且程式碼可能會變得很龐大
因此destruct這個技巧可以幫助我們大幅度縮縮短取資料的過程。
只要物件的屬性名稱跟變數一樣,就可以利用destruct的方式將資料取出
例如:
https://ithelp.ithome.com.tw/upload/images/20220911/20145703KFACzr7cR0.png

明天我們要繼續來看 React的 Status
(React好像太多了,有點寫不完XD)


上一篇
Day 6 動手操作看看React - 2 (柬埔寨完結)
下一篇
Day 8 React State
系列文
跳脫MVC,Laravel + React 建立電商網站30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言