React學習手記4-元件分類(受控元件和非受控元件)

雨田666發表於2019-03-06

元件可以按不同角度做分類,這次從表單元素的使用開始。不同於div、span等元素只需根據狀態來展示內容,表單元素自身可以維護一些狀態,但是預設不受React控制。比如,一個input輸入框,會隨使用者的輸入而改變。這樣的互動行為明顯違背了React的基本原則--狀態的改變必須通過元件的state。

受控元件

為了達到由React來控制表單元素的值,可以在使用者和表單元素髮生互動時控制表單元素的行為,從而保證元件的state成為表單元素狀態的唯一來源,也就是表單元素的值是由React來管理。

不同表單元素實現的方式不一樣

文字框

文字框包含型別為text的<input>元素和<textarea>元素。通過表單元素的value屬性設定表單元素的值,通過onChange事件監聽值得變化,並將變化同步到React元件的state中

class NameForm extends React.Component {
  constructor(props) {
    super(props);
    this.state = {name: ''};
    this.handleChange = this.handleChange.bind(this);
  }
  handleChange(event) {
    const target = event.target;
    this.setState({[target.name]: target.value});
  }
  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <label>
          Name:
          <input name="name" type="text" value={this.state.name}  onChange={this.handleChange} />
        </label>
        <input type="submit" value="Submit" />
      </form>
    );
  }
}複製程式碼

下拉選單

<select name="cars">
    <option value="volvo">Volvo</option>
    <option value="saab">Saab</option>
    <option value="fiat" selected="selected">Fiat</option>
</select>複製程式碼

React與原生使用selcted定義選中項不同,它通過在<selcet>上定義value屬性來決定那個<option>元素處於選中項。

class NameForm extends React.Component {
  constructor(props) {
    super(props);
    this.state = {value: ''};
    this.handleChange = this.handleChange.bind(this);
  }
  handleChange(event) {
    this.setState({value: event.target.value});
  }
  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <label>
          Name:
            <select name="cars" value={this.state.value} onChange={this.handleChange}>
                <option value="volvo">蘋果</option>
                <option value="saab">香蕉</option>
                <option value="fiat">鳳梨</option>          </select>
        </label>
        <input type="submit" value="Submit" />
      </form>
    );
  }
}複製程式碼

核取方塊和單選框

型別為checkbox和radio的<input>元素,受控方式不同於text型別。React控制的不在是value屬性,而是checked屬性。

class NameForm extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
        apple: false,
        orange: false
    };
    this.handleChange = this.handleChange.bind(this);
  }
  handleChange(event) {
    const target = event.target;
    this.setState({[target.name]: target.checked});
  }
  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <label>
          Apple
          <input name="apple" type="checkbox" vlaue="apple" checked={this.state.apple}  onChange={this.handleChange} />
        </label>
        <label>
          orange
          <input name="apple" type="checkbox" vlaue="orange" checked={this.state.orange}  onChange={this.handleChange} />      </label>

        <input type="submit" value="Submit" />      </form>
    );
  }
}複製程式碼

非受控元件

受控元件需要每個元素繫結onChange事件,比較繁瑣。另一種方式就是使用非受控元件,不用React來管理狀態,所以需要一種方式來獲取到表單元素的值。

ref

React提供了一個特殊的屬性ref,用來引用React元件或DOM元素的例項,故可以通過為表單元素定義ref屬性來獲取元素的值。

handleSubmit(event){
    // 通過this.input 獲取到input元素的值
    alert(“value is" + this.input.vlaue);
    event.preventDefault()
}

//this.input 指向當前input元素
<input type="text" ref={(inptu) => this.input = input} />複製程式碼

ref值是個函式,會接受當前元素作為引數,然後把input賦值給了this.input。進而可以在元件的其他地方通過this.input獲取這個元素。

defaultValue

因為使用非受控元件,通常需要設定預設值,但是無法再通過value屬性設定。所以可以使用defaultValue屬性設定預設值。類似的,select和textarea也可以設定defalutValue,<input type="checkbox"> 和<input type="radio">則設定defaultChecked屬性設定預設值。


相關文章