受控元件與非受控元件

2018不下雪發表於2018-04-12

受控元件與非受控元件:是否受狀態控制。

1.用受控元件實現雙向資料繫結

我們來實現一個react的雙向資料繫結
讓輸入框輸入值,下面的顯示跟著變化

import React,{Component} from 'react';
import ReactDOM from 'react-dom';

class Input extends Component{
    constructor(){
        super();
        this.state={val:''}
    }
    render(){
        return (<div>
            <input type="text" value={this.state.val}/>
            {this.state.val}
        </div>)
    }
}
ReactDOM.render(<Input/>, document.querySelector('#root'));
複製程式碼

但是結果和我們想象的不一樣:輸入框不能輸入值。這是因為input的value取的是state中的val。但是val的值一直是空。 改變state的唯一方式setState

  • 受狀態控制的元件,必須要有onChange方法,否則不能使用.
  • 受控元件可以賦予預設值(官方推薦使用受控元件)
import React,{Component} from 'react';
import ReactDOM from 'react-dom';

class Input extends Component{
    constructor(){
        super();
        this.state={val:'100'}
    }
    handleChange=(e)=>{//e是事件源
        let val=e.target.value;
        this.setState({val});
}
    render(){
        return (<div>
            <input type="text" value={this.state.val} onChange={this.handleChange}/>
            {this.state.val}
        </div>)
    }
}
ReactDOM.render(<Input/>, document.querySelector('#root'));
複製程式碼

簡單功能實現,輸入框值,與顯示值統一。這就是受控元件,受狀態控制。

2.受控元件公用方法的狀態控制

兩個輸入框實現求和功能,如果使用兩個onchange事件,會造成程式碼的冗餘。我們現在把他們合在一起。

import React,{Component} from 'react';
import ReactDOM from 'react-dom';

class Sum extends Component{
    constructor(){
        super();
        this.state={a:1,b:1}
    }
    //key表示的當前狀態改的是哪一個
    //e表示的是事件源
    handleChange=(key,e)=>{//處理多個輸入框的值對映到狀態的方法
        let val=e.target.value;
        this.setState({[key]:val});
}
    render(){
        return (<div>
            <input type="text" value={this.state.a} onChange={(e)=>{
                this.handleChange('a',e)
            }}/>
            <input type="text" value={this.state.b} onChange={(e)=>{
                this.handleChange('b',e)
            }}/>
            {this.state.a+this.state.b}
        </div>)
    }
}
ReactDOM.render(<Sum/>, document.querySelector('#root'));
複製程式碼

這樣就可以通過一個方法實現兩個onchange事件的功能,不過上面是兩個字串的拼接,需要轉為數字再相加,在這就不做了。

3.非受控元件(不受狀態控制)

import React,{Component} from 'react';
import ReactDOM from 'react-dom';

//輸入框value值不受狀態控制,不能初始化預設值
class Sum extends Component{
    constructor(){
        super();
        this.state={result:''}
    }
    //通過ref設定的屬性,可以通過this.refs獲取到對應的dom元素
    handleChange=()=>{
        let result=this.refs.a.value+this.refs.b.value;
        this.setState({result});
    }
    render(){
        return (<div onChange={this.handleChange}>//運用冒泡的機制不在兩個input中新增onchange事件
            <input type="text" ref="a"/>
            <input type="text" ref="b"/>
            {this.state.result}
        </div>)
    }
}
ReactDOM.render(<Sum/>, document.querySelector('#root'));
複製程式碼

上面這種實現方式,兩個輸入框不受狀態的控制。通過操作dom獲取到value值,然後進行相加。這就是非受控元件,他與受控元件的區別就是不可以給預設值。

ref的另外一種實現方式(推薦)

import React,{Component} from 'react';
import ReactDOM from 'react-dom';
import ErrorBoundary from './components/ErrorBoundary';
import Counter from "./components/Counter";
import Todos from "./components/Todos";
//輸入框value值不受狀態控制,不能初始化預設值
class Sum extends Component{
    constructor(){
        super();
        this.state={result:''}
    }
    //通過ref設定的屬性,可以通過this.refs獲取到對應的dom元素
    handleChange=()=>{
        let result=this.refs.a.value+this.b.value;
        this.setState({result});
    }
    render(){
        return (<div onChange={this.handleChange}>//運用冒泡的機制不在兩個input中新增onchange事件
            <input type="text" ref="a"/>
            //x代表真實的dom  ,把元素掛載到了當前例項上
            <input type="text" ref={x=>this.b=x}/>
            {this.state.result}
        </div>)
    }
}
ReactDOM.render(<Sum/>, document.querySelector('#root'));
複製程式碼

第二個輸入框中ref給了一個箭頭函式,x代表真實的dom,把真實dom賦值給當前例項中

相關文章