React(三):受控組件與非受控組件

一、受控組件html

在HTML當中,像<input>,<textarea>, 和 <select>這類表單元素會維持自身狀態,並根據用戶輸入進行更新。但在React中,可變的狀態一般保存在組件的狀態屬性中,而且只能用 setState() 方法進行更新。react

咱們經過使react變成一種單一數據源的狀態來結合兩者。React負責渲染表單的組件仍然控制用戶後續輸入時所發生的變化。相應的,其值由React控制的輸入表單元素稱爲「受控組件」。segmentfault

因爲 value 屬性是在咱們的表單元素上設置的,所以顯示的值將始終爲 React數據源上this.state.value 的值。因爲每次按鍵都會觸發 handleChange 來更新當前React的state,所展現的值也會隨着不一樣用戶的輸入而更新。bash

<input type="text" value={this.state.value} onChange={this.handleChange}  />複製代碼

二、非受控組件架構

要編寫一個非受控組件,而非爲每一個狀態更新編寫事件處理程序,你能夠 使用 ref 從 DOM 獲取表單值。
dom

在 React 的生命週期中,表單元素上的 value 屬性將會覆蓋 DOM 中的值。使用非受控組件時,一般你但願 React 能夠爲其指定初始值,但再也不控制後續更新。要解決這個問題,你能夠指定一個 defaultValue 屬性而不是 value
性能

<input type="text" defaultValue={'1232'} ref={this.input} />複製代碼

舉例:ui

class NameForm extends React.Component {
  constructor(props) {
    super(props);
    this.handleSubmit = this.handleSubmit.bind(this);
    this.handleChange = this.handleChange.bind(this);
    
    this.input = React.createRef();
    this.state = {
      value:'567'
    }
  }

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

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

ReactDOM.render(
  <NameForm />,
  document.getElementById('root')
);複製代碼

在 CodePen 上嘗試。
this

三、對比受控組件和非受控組件spa

將輸入的字母轉化爲大寫展現

<input
    type="text"
    value={this.state.value}
    onChange={(e) => {
        this.setState({
            value: e.target.value.toUpperCase(),
        });
    }}
/>複製代碼

直接展現輸入的字母

<input
    type="text"
    defaultValue={this.state.value}
/>複製代碼

a、性能上的問題

在受控組件中,每次表單的值發生變化,都會調用一次onChange事件處理器,這確實會帶來性能上的的損耗,雖然使用費受控組件不會出現這些問題,但仍然不提倡使用非受控組件,這個問題能夠經過Flux/Redux應用架構等方式來達到統一組件狀態的目的.

b、是否須要事件綁定

使用受控組件須要爲每個組件綁定一個change事件,而且定義一個事件處理器來同步表單值和組件的狀態,這是一個必要條件.固然,某些狀況可使用一個事件處理器來處理多個表單域


import React, { Component } from 'react';

class Controlled extends Component {
    constructor(...args) {
        super(...args);
        this.state = {
            name: 'xiaoming',
            age: 18,
        };
    }
    handleChange = (name, e) => {
        const { value } = e.target;
        this.setState({
            [name]: value,
        });
    }
    render() {
        const { name, age } = this.state;
        return (
            <div>
                <input type="text" value={name} onChange={this.handleChange.bind(this, 'name')} />
                <input type="text" value={age} onChange={this.handleChange.bind(this, 'age',)} />
            </div>
        );
    }
}

export default Controlled;複製代碼


參考:

https://segmentfault.com/a/1190000012404114#articleHeader2

https://react.docschina.org/docs/uncontrolled-components.html

相關文章
相關標籤/搜索