iT邦幫忙

2022 iThome 鐵人賽

DAY 9
0
Modern Web

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

Day 9 關於React的其他特性 -1

  • 分享至 

  • xImage
  •  

昨天有說到因為篇幅的問題,接下來的官方文件學習之路腳步會有所加快,廢話不多說 馬上進入正題。

Event

有接觸過Jquery或原生JS的同學們對於事件處理一定非常熟悉,所以關於原生的事件我這裡就簡單敘述。
原生的事件邏輯基本上就是:query selector 選到目標Dom → 掛載事件監聽 → 寫事件處觸發要做什麼事情。
就是一套基本的萬用邏輯來處理畫面跟使用者的互動

另外有一種寫法可以不用去選擇dom掛監聽,作法就是直接在html element上面加 事件監聽。
React主要都是採用後者的方法,當element render到畫面上時,已經把監聽掛好了
React跟html事件監聽不同的地方是: html 會把function寫成字串 例如:

onClick="goHome()"

而React會這樣寫:

onClick={goHome} //注意 這裡不用括號

如果這裡加上括號會怎樣? A:會直接執行,因為在Js的事件中 我們需要去呼叫一個function就是直接寫function Name + 括號

所以當程式碼執行到goHome的時候 會直接執行
那如果我們想要在這個地方加入parameter給goHome這個function怎麼辦?
其實解法很簡單,我們只要在goHome外面再包一層function 就可以了

ocClick={ () => { goHome("Taipei City") }}

另外,如果要使用 "避免html預設功能"
就需要使用e.preventDefault 不能夠使用return false這個古老的寫法XD

接下來我這裡想針對這個範例做比較深入的理解:

class Toggle extends React.Component {
  constructor(props) {
    super(props);
    this.state = {isToggleOn: true};


    // 為了讓 `this` 能在 callback 中被使用,這裡的綁定是必要的:
    this.handleClick = this.handleClick.bind(this);
  }


  handleClick() {
    this.setState(prevState => ({
      isToggleOn: !prevState.isToggleOn
    }));
  }

  render() {
    return (

      <button onClick={this.handleClick}>
        {this.state.isToggleOn ? 'ON' : 'OFF'}
      </button>
    );
  }
}

【範例小補充】
在看這個範例之前我想先講一下關於bind這個東西,bind在中文就是綁定的意思
接下來我們直接看實例:

let staff = {
    name: "bennett",
    age: 23,
    education: "university"
}

function bennett(){
    console.log(this.name);
}
bennett();

這時候會出現undefined,因為這個時候對於bennett 這個function 來說 它的this指的是window object
所以我們要把指定物件綁定到這個function身上,改成如下

let staff = {
    name: "bennett",
    age: 23,
    education: "university"
}

function bennett(){
    console.log(this.name);
}
let bennettName = bennett.bind(staff);
bennettName(); //bennett

接下來我們正式解讀這個範例
首先我們先看construct,起手式的prop就不用看了。
繼續往下看 可以看到創立了一個新的state ,內容包含isToggleOn是true
然後再往下可以看到這裡把this綁定到handleClick這個function之中
所以handleClick如果使用this,就會拿到construct的this object
然後
看到Component render畫面的地方做了一個三元運算子的判斷,如果isToggleOn是true就出現on反之off

https://ithelp.ithome.com.tw/upload/images/20220913/20145703mjYDah4C42.jpg

接著可以看到onclick 去呼叫handleClick的function
這個function 裡面去setState isToggleOn的數值(這裡為了確保每次的state都是最新,有用到arrow function + 兩個參數 的方式,忘記的朋友們可以去昨天的文章複習一下)
---React 事件結束---

條件Render

如果是平常就在進行網頁開發的工程師,一定都會遇到某些條件才需要顯示/ 不同條件下要顯示不同內容的這個問題;在React之中可以利用建立不同的Component並根據state的狀態來判斷要render誰
官方範例,這個是根據props的資訊來判斷要回傳哪個component

function UserGreeting(props) { 
  return <h1>Welcome back!</h1>; 
} 
function GuestGreeting(props) { 
  return <h1>Please sign up.</h1>; 
} 
function Greeting(props) { 
  const isLoggedIn = props.isLoggedIn; 
  if (isLoggedIn) { 
    return <UserGreeting />; 
  } 
  return <GuestGreeting />; 
} 
const root = ReactDOM.createRoot(document.getElementById('root'));  
// Try changing to isLoggedIn={true}: 
root.render(<Greeting isLoggedIn={false} />);

當然也可以利用過去所學到的其他技巧來判斷

class LoginControl extends React.Component { 
    //這裡是一個component
  constructor(props) { 
    super(props); 
    /*要把this 物件分享,所以這裡要綁定*/
    this.handleLoginClick = this.handleLoginClick.bind(this); 
    this.handleLogoutClick = this.handleLogoutClick.bind(this); 
    this.state = {isLoggedIn: false}; 
  } 
  handleLoginClick() { 
    //這裡是function
    this.setState({isLoggedIn: true}); 
  } 
  handleLogoutClick() { 
    //這裡是function
    this.setState({isLoggedIn: false}); 
  } 
  render() { 
    const isLoggedIn = this.state.isLoggedIn; 
    let button; 
    if (isLoggedIn) { 
      button = <LogoutButton onClick={this.handleLogoutClick} />; //向下資料流實作範例
    } else { 
      button = <LoginButton onClick={this.handleLoginClick} />; //向下資料流實作範例
    } 
    return ( 
      <div> 
        <Greeting isLoggedIn={isLoggedIn} /> 
        {button} 
      </div> 
    ); 
  } 
} 
function UserGreeting(props) { 
//這裡是一個component
  return <h1>Welcome back!</h1>; 
} 
function GuestGreeting(props) { 
//這裡是一個component
  return <h1>Please sign up.</h1>; 
} 
function Greeting(props) { 
//這裡是一個component
  const isLoggedIn = props.isLoggedIn; 
  if (isLoggedIn) { 
    return <UserGreeting />; 
  } 
  return <GuestGreeting />; 
} 
function LoginButton(props) { 
//這裡是一個component , 這裡會收到上面丟下來function
  return ( 
    <button onClick={props.onClick}> 
      Login 
    </button> 
  ); 
} 
function LogoutButton(props) { 
//這裡是一個component , 這裡會收到上面丟下來function
  return ( 
    <button onClick={props.onClick}> 
      Logout 
    </button> 
  ); 
} 
const root = ReactDOM.createRoot(document.getElementById('root'));  
root.render(<LoginControl />);

因為這裡的code比較長,比較容易混淆 所以我自己做了一些簡單的解析:
畫面邏輯:
1. 一開始將LoginControl render到root,所以可以到LoginControl看看。
2. LoginControl是一個component 本身的state 預設是false
3. 接著到LoginControl render畫面的地方,可以看到針對state 的true false 會丟到不同的component拿按鈕
4. 這裡注意LoginControl有使用到向下資料流,把如果被點擊需要觸發的function當成prop丟給LoginButton或LogoutButton
5. LoginButton或LogoutButton各自回傳button回去給LoginControl
6. 這時候LoginControl 已經取得了關於button的element
7. 繼續往下看 LoginControl return 了一個Greeting的component並把false當成props丟下去
8. Greeting收到false之後回傳了 GuestGreeting這個component回去

點擊行為發生時:
1. LoginButton 或者 LogoutButton觸發onclick,去找相對應的function執行(假設觸發handleLoginClick)
2. 這時候handleLoginClick function 把state改成true,因為state的更新,所以畫面會重新render
3. isLoggedIn變成了true,所以buttom變數會到LogoutButton Component來取得對應的button資料(這裡一樣向下把對應的function當成props丟出)
4. 這時候LoginControl 已經取得了關於button的element
5. 繼續往下看 LoginControl return 了一個Greeting的component並把true當成props丟下去
6. Greeting收到true之後回傳了 UserGreeting這個component回去

官方有另外提供兩種比較簡短的if、else寫法,有興趣的話可以到文件看看
另外還有透過return Null的方式來防止component Render 礙於篇幅,這裡就不做範例解析了~

明天會繼續介紹react的其他特性,不過會挑重點講,因為當初幫react設定的篇幅就是10篇


上一篇
Day 8 React State
下一篇
Day 10 React的其他特性 -2
系列文
跳脫MVC,Laravel + React 建立電商網站30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言