Skip to content

非受控组件

在大多数情况下,推荐使用受控组件来处理表单数据。在一个受控组件中,表单数据是由React组件来管理的。另一种代替方案是使用非受控组件,这时候表单数据将交给DOM节点来处理。

要编写一个非受控组件,而不是为每个状态更新都编写数据处理函数。你可以使用ref来从DOM节点中选取表单数据。 例如,下面的代码使用非受控组件接收一个表单的值:

class NameForm extends React.Component {
    constructor(props){
        super(props)
        this.handleSubmit = this.handleSubmit.bind(this)
        this.input = React.createRef();
    }
    handleSubmit (){
        alert('a name was submit :'+ this.input.current.value)
        event.preventDefault();
    }
    render (){
        return (
            <form onSubmit = { this.handleSubmit }>
                <label htmlFor="name"> Name: </label>
                <input type="text" ref={this.input}  />
                <input type="submit" value="submit" />
            </form>
        )
    }

}

ReactDOM.render(<NameForm  /> , document.querySelector('#root'))

因为非受控组件将真实数据储存在DOM节点中,所以在使用非受控组件时,有时候反而更容易同时继承React和非React代码。如果你不介意代码的美观性,并且希望快速编写代码,使用非受控组件往往可以减少你的代码量。否则,你应该使用受控组件。

默认值

在React渲染生命周期时,表单元素上的value将会覆盖DOM节点中的值。在非受控组件中,你经常希望React能赋予组件一个初始值,但是不去控制后续的更新,这种情况你可以指定一个defaultValue属性,而不是value

render (){
    return (
        <form onSubmit = { this.handleSubmit }>
            <label htmlFor="name"> Name: </label>
            <input type="text" ref={this.input}  id="name" defaultValue="blob" />
            <input type="submit" value="submit" />
        </form>
    )
}

同样,<input type="checkbox"><input type="radio"> 支持 defaultChecked,<select><textarea> 支持 defaultValue

文件输入

在HTML中,<input type="file" />可以让用户选择一个或多个文件上传到服务器,或者通过使用File API进行操作。

<input type="file"  />

在React中,<input type="file" />始终是一个非受控组件,因为它的值只能由用户设置,而不能通过代码控制。 使用FileAPI与文件进行交互:

class FileInput extends React.Component{
    constructor(props){
        super(props)
        this.handleSubmit = this.handleSubmit.bind(this)
        this.input = React.createRef();
    }
    handleSubmit (event){
        event.preventDefault();
        console.log(this.input.current.files[0])
    }
    render (){
        return (
            <form onSubmit = { this.handleSubmit }>
                <label htmlFor="name"> Name: </label>
                <input type="file" ref={this.input}  id="name"  />
                <input type="submit" value="submit" />
            </form>
        )
    }
}