【React系列】受控組件(Controlled Components)和不受控組件

受控組件

表單

HTML 表單用於蒐集不一樣類型的用戶輸入。瀏覽器

<form> 元素

<form> 元素定義 HTML 表單:函數

<form>
 .
form elements
 .
</form>

表單元素

表單元素指的是不一樣類型的 input 元素、複選框、單選按鈕、提交按鈕等等。
當用戶提交表單時瀏覽器會打開一個新頁面,若是你但願 React 中保持這個行爲,也能夠工做。可是多數狀況下,用一個處理表單提交併訪問用戶輸入到表單中的數據的 JavaScript 函數也很方便。實現這一點的標準方法是使用一種稱爲「受控組件(controlled components)」的技術。this

受控組件(Controlled Components)

在 HTML 中,表單元素如 <input>,<textarea> 和 <select> 表單元素一般保持本身的狀態,並根據用戶輸入進行更新。而在 React 中,可變狀態通常保存在組件的 state(狀態) 屬性中,而且只能經過 setState() 更新。code

咱們能夠經過使 React 的 state 成爲 「單一數據源原則」 來結合這兩個形式。而後渲染表單的 React 組件也能夠控制在用戶輸入以後的行爲。這種形式,其值由 React 控制的輸入表單元素稱爲「受控組件」。component

一個常規的受控組件的形式例子:orm

class NameForm extends React.Component {
  constructor(props) {
    super(props);
    this.state = {value: ''};

    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }

  handleChange(event) {
    this.setState({value: event.target.value});
  }

  handleSubmit(event) {
    alert('A name was submitted: ' + this.state.value);
    event.preventDefault();
  }

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <label>
          Name:
          /*① 設置表單元素的value屬性以後,其顯示值將由this.state.value決定,以知足React狀態的同一數據理念。*/
          /*② 每次鍵盤敲擊以後會執行handleChange方法以更新React狀態,顯示值也將隨着用戶的輸入改變。*/
          <input type="text" value={this.state.value} onChange={this.handleChange} />
        </label>
        <input type="submit" value="Submit" />
      </form>
    );
  }
}

因爲 value 屬性設置在咱們的表單元素上,顯示的值老是 this.state.value,以知足 state 狀態的同一數據理念。因爲 handleChange 在每次敲擊鍵盤時運行,以更新 React state(狀態),顯示的值將更新爲用戶的輸入。事件

對於受控組件來講,每一次 state(狀態) 變化都會伴有相關聯的處理函數。這使得能夠直接修改或驗證用戶的輸入。好比,若是咱們但願強制 name 的輸入都是大寫字母,能夠這樣來寫 handleChange 方法:ip

handleChange(event) {
  this.setState({value: event.target.value.toUpperCase()});
}

受控表單的表單元素

上面例子中是以input爲例來寫的,其實其餘的表單元素基本形式是差很少的。element

textare

<textarea value={this.state.value} onChange={this.handleChange} />

select

<select value={this.state.value} onChange={this.handleChange}>
……
</select>

處理多個輸入元素

當您須要處理多個受控的 表單元素時,您能夠爲每一個元素添加一個 name 屬性,而且讓處理函數根據 event.target.name 的值來選擇要作什麼。開發

因爲 setState() 自動將部分狀態合併到當前狀態,因此咱們只須要調用更改的部分便可。

受控組件的替代方案

有時使用受控組件有些乏味,由於你須要爲每個可更改的數據提供事件處理器,並經過 React 組件管理全部輸入狀態。當你將已經存在的代碼轉換爲 React 時,或將 React 應用程序與非 React 庫集成時,這可能變得特別煩人。在這些狀況下,您可能須要使用不受控的組件,用於實現輸入表單的替代技術。

不受控組件

在大多數狀況下,咱們推薦使用受控組件來實現表單。在受控組件中,表單數據由 React 組件負責處理。另一個選擇是不受控組件,其表單數據由 DOM 元素自己處理。

要編寫一個未控制組件,你可使用一個 ref 來從 DOM 得到 表單值,而不是爲每一個狀態更新編寫一個事件處理程序。

例如,在不受控組件中,如下代碼接受一個單獨的名字 :

class NameForm extends React.Component {
  constructor(props) {
    super(props);
    this.handleSubmit = this.handleSubmit.bind(this);
  }

  handleSubmit(event) {
    alert('A name was submitted: ' + this.input.value);
    event.preventDefault();
  }

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <label>
          Name:
          <input type="text" ref={(input) => this.input = input} />
        </label>
        <input type="submit" value="Submit" />
      </form>
    );
  }
}

受控組件與不受控組件的選取

由於不受控組件的數據來源是 DOM 元素,當使用不受控組件時很容易實現 React 代碼與非 React 代碼的集成。若是你但願的是快速開發、不要求代碼質量,不受控組件能夠必定程度上減小代碼量。不然。你應該使用受控組件。

相關文章
相關標籤/搜索