6 受控组件与非受控组件

受控组件

  • 表单的值,受到state控制
  • 需要自行监听onChange,更新state
  • 对比非受控组件
    import React from 'react'
    
    class FormDemo extends React.Component {
        constructor(props) {
            super(props)
            this.state = {
                name: 'test',
                info: '个人信息',
                city: 'shenzhen',
                flag: true,
                gender: 'male'
            }
        }
        render() {
    
            // 受控组件
            // return <div>
            //     <p>{this.state.name}</p>
            //     <label htmlFor="inputName">姓名:</label> {/* 用 htmlFor 代替 for */}
            //     <input id="inputName" value={this.state.name} onChange={this.onInputChange}/>
            // </div>
    
            // textarea - 使用 value
            return <div>
                <textarea value={this.state.info} onChange={this.onTextareaChange}/>
                <p>{this.state.info}</p>
            </div>
    
            // // select - 使用 value
            // return <div>
            //     <select value={this.state.city} onChange={this.onSelectChange}>
            //         <option value="beijing">北京</option>
            //         <option value="shanghai">上海</option>
            //         <option value="shenzhen">深圳</option>
            //     </select>
            //     <p>{this.state.city}</p>
            // </div>
    
            // // checkbox
            // return <div>
            //     <input type="checkbox" checked={this.state.flag} onChange={this.onCheckboxChange}/>
            //     <p>{this.state.flag.toString()}</p>
            // </div>
    
            // // radio
            // return <div>
            //     male <input type="radio" name="gender" value="male" checked={this.state.gender === 'male'} onChange={this.onRadioChange}/>
            //     female <input type="radio" name="gender" value="female" checked={this.state.gender === 'female'} onChange={this.onRadioChange}/>
            //     <p>{this.state.gender}</p>
            // </div>
    
            // 非受控组件 - 后面再讲
        }
        onInputChange = (e) => {
            this.setState({
                name: e.target.value
            })
        }
        onTextareaChange = (e) => {
            this.setState({
                info: e.target.value
            })
        }
        onSelectChange = (e) => {
            this.setState({
                city: e.target.value
            })
        }
        onCheckboxChange = () => {
            this.setState({
                flag: !this.state.flag
            })
        }
        onRadioChange = (e) => {
            this.setState({
                gender: e.target.value
            })
        }
    }
    
    export default FormDemo

非受控组件

  • ref 访问 DOM元素或者某个组件实例的句柄
    • ref 有两种使用方式
      • React.createRef() 创建ref,通过ref访问DOM元素或者某个组件实例
      • React.forwardRef() 函数组件中传递ref,通过ref访问DOM元素或者某个组件实例
  • ref 有两种使用场景
    • defaultValuedefaultChecked
    • 手动操作DOM元素

使用场景

  • 必须手动操作DOM元素,setState实现不了
  • 文件上传<input type="file" />
  • 某些富文本编辑器,需要传入DOM元素
    import React from 'react'
    
    class App extends React.Component {
        constructor(props) {
            super(props)
            this.state = {
                name: 'test',
                flag: true,
            }
            this.nameInputRef = React.createRef() // 创建 ref
            this.fileInputRef = React.createRef()
        }
        render() {
            // // input defaultValue
            // return <div>
            //     {/* 使用 defaultValue 而不是 value ,使用 ref */}
            //     <input defaultValue={this.state.name} ref={this.nameInputRef}/>
            //     {/* state 并不会随着改变 */}
            //     <span>state.name: {this.state.name}</span>
            //     <br/>
            //     <button onClick={this.alertName}>alert name</button>
            // </div>
    
            // // checkbox defaultChecked
            // return <div>
            //     <input
            //         type="checkbox"
            //         defaultChecked={this.state.flag}
            //     />
            // </div>
    
            // file
            return <div>
                <input type="file" ref={this.fileInputRef}/>
                <button onClick={this.alertFile}>alert file</button>
            </div>
    
        }
        alertName = () => {
            const elem = this.nameInputRef.current // 通过 ref 获取 DOM 节点
            alert(elem.value) // 不是 this.state.name
        }
        alertFile = () => {
            const elem = this.fileInputRef.current // 通过 ref 获取 DOM 节点
            alert(elem.files[0].name)
        }
    }
    
    export default App
Last Updated:
Contributors: leeguooooo