React-(三)組件基本

組件狀態:state 與 setState

state

  • 新增一個「Message.js」檔案
  • 第5行,定義一個 state,本身是一個物件
    • 其中有一個 text,並給予預設值”Hi”
  • 第11行,將要 render 出來的東西用{}包著

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    // Message.js
    import React, { Component } from 'react';

    class Message extends Component {
    state = {
    text: "Hi",
    }
    render() {
    return (
    <div>
    <h3>{this.state.text}</h3>
    </div>
    );
    }
    }

    export default Message;
  • 將 Message 組件掛載到 DOM 元素中

    1
    2
    3
    4
    5
    6
    //index.js
    import React from 'react';
    import ReactDom from 'react-dom'
    import Message from './Message'

    ReactDom.render( <Message/> , document.getElementById('root'));
  • 執行指令

    1
    yarn start
  • 可以看到瀏覽器中的畫面, 顯示 text 的初始值”Hi”

setState

  • 第7行,自定義一個 sayHi 方法
  • 第16行,在 button 上面綁定 onClick 事件(JSX的事件要用駝峰命名),並且觸發 sayHi 方法

在箭頭函式中的 this 代表被宣告時的 context,也因此在組件中的方法若用箭頭函式來宣告,其中的 this 就一定會代表組件本身

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import React, { Component } from 'react';

class Message extends Component {
state = {
text: "Hi",
}
sayHi = () => {
this.setState({
text: "Hi"
})
}
render() {
return (
<div>
<h3>{this.state.text}</h3>
<button onClick={this.sayHi}>Say Hi</button>
</div>
);
}
}

export default Message;

setState的參數要傳入一個物件是一個 partial state(部分的狀態),也就是說不需要傳入完整的state

  • 下方案例的 state 有”title” 跟 “message”
  • 可是在 setState 時,只需要把部分待改變的狀態傳進去,因此只傳 title 就只會改變該值的狀態
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    class Message extends Component{
    state = {
    title:"",
    message:""
    },
    sayHi = ()=>{
    this.setState({
    title:"Hello"
    });
    }
    }

組件的自訂函式

在組件中的自訂函式,有兩種方法宣告:

  • 箭頭函式:可以確保 this 代表組件本身
    • 第 17 行跟第 21 行執行 sayHi 函式時,因為 sayHi 函式以箭頭函式的形式宣告,因此其中的 this 都代表該函式被宣告時的 context,也就是 Message 物件
  • 一般函式:有自己的context ,因此 this 會依據不同的情況而有所不同
    • 第 18 行,用此方法執行 sayHello 函式,則 sayHello 函式中的 this 代表執行時的 this (第14行的 this)
    • 第 22 行,函式綁定在 button 事件上,則 sayHello 函式中的 this 就會代表 button 元素本身,如此一來就會出錯
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      //箭頭函式
      class Message extends Component{
      // ...略
      sayHi = () => {
      this.setState({
      text: "Hi"
      })
      }
      //一般函式
      sayHello(){
      this.setState({
      text: "Hello"
      })
      }
      render() {
      this.sayHi();
      this.sayHello();//
      return (
      <div>
      <button onClick={this.sayHi}>Say Hi</button>
      <button onClick={this.sayHello}>Say Hello</button>
      </div>
      );
      }
      }

為了避免函式中的 this 指向出錯,可以透過在建構函式(Construstor)中,去重新綁定函式的 context

  • bind 是函式的方法,每一個(自訂)函式都可以有 bind 這個方法
  • bind 方法傳入的參數,代表該函式要綁定的 context(不論用什麼方式執行該函式,它的 context 都會固定是該被傳入的參數)
  • 第 5 行,bind(this)的 this,代表 Message 組件,所以把組件傳入定義該函式綁定的 context
  • 第 5 行,this.sayHello.bind(this)會回傳出一個函式,並將該函式 assign 回原先的this.sayHello
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    class Message extends Component{
    // ...略
    constructor(props){
    super(props);
    this.sayHello = this.sayHello.bind(this);
    }
    sayHello(){
    this.setState({
    text: "Hello"
    })
    }
    render() {
    this.sayHello();
    return (
    <div>
    <button onClick={this.sayHello}>Say Hello</button>
    </div>
    );
    }
    }

props:上面傳下來的屬性

如果父組件要傳值給子組件,可以透過 props 傳遞

  • 在父組件使用子組件的 tag 中,可以自訂 props 傳值
  • 如果 props 的值非字串,則要用 {} 括起來
  • 如果是直接在 opening tag 跟 closing tag 之間的內容,則子組件要用 this.props.children 存取

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    //List.js(父組件)
    // ...略
    import Item from "./Item";
    class List extends Component{
    render(){
    return (
    <ol>
    <Item text="apple" count={2}>On stock</Item>
    <Item text="orange" count={1}>On stock</Item>
    <Item text="green" count={3}>On stock</Item>
    <Item text="blue" count={0}>Sold out</Item>
    </ol>
    )
    }
    }
    // ...略
  • 從父組件中傳來的 props,會存為子組件的 props,因此可以使用 this.props.xxx 呼叫出來

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    //Item.js(子組件)
    // ...略

    class Item extends Component{
    render(){
    return (
    <li>{this.props.text}:{this.props.count}/{this.props.children}</li>
    )
    }
    }
    // ...略

© 2020 Leah's Blog All Rights Reserved. 本站访客数人次 本站总访问量
Theme by hiero