受控组件与非受控组件

6,478 阅读3分钟

受控组件与非受控组件:是否受状态控制。

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赋值给当前实例中