1. 程式人生 > 實用技巧 >受控元件 VS 非受控元件

受控元件 VS 非受控元件

寫在前面

React 中受控元件和非受控元件的概念是針對於表單元素的。
表單元素的工作方式和其他 DOM 元素有些不同,簡單來說,其他 DOM 元素的 state 資料都是由開發者直接控制和維護的,但是表單元素的 state 是由表單自己維護的,使用者通過輸入的方式改變表單的 state 資料。
表單資料預設是由自己維護的,那麼能否將表單的資料交給開發者維護呢?這就衍生出受控元件和非受控元件的概念。

官方解釋:React 受控元件React 非受控元件

1. 受控元件

受控元件,顧名思義,就是表單元件資料受開發者的控制,也就是說開發者可以通過 JavaScript 對頁面中表單的內容進行改變和控制。

<input value={x} onChange={fn}/>

class App extends React.Component{
    constructor(props){
        super(props)
        this.state = {val: ''}  
    } 
    handleChange = (e)=>{
        this.setState({val: e.target.value})
    }
    handleSubmit = (e)=>{
        e.preventDefault();
        console.log(this.state.val)
    }
    handleClick = ()=>{
        this.setState({val: 'vin'})
    }
    render(){
        return (
            <div>
                我是App元件
                <form onSubmit={this.handleSubmit}>
                    <label>
                        名字:<input type="text" value={this.state.val} onChange={this.handleChange}/>
                    </label>
                    <label>
                        <input type="submit"/>
                    </label>
                </form>
                <button onClick={this.handleClick}>改變名字為 vin</button>
            </div>
        )
    }
}

自定義表單元件的受控元件是一樣的控制方式

const MyInput = (props)=>{
    return (
        <form onSubmit={props.onSubmit}>
            <label>
                名字:<input type="text" value={props.value} onChange={props.onChange}/>
            </label>
            <label>
                <input type="submit"/>
            </label>
        </form>
    )
}

class App extends React.Component{
    constructor(props){
        super(props)
        this.state = {val: ''}  
    } 
    handleChange = (e)=>{
        this.setState({val: e.target.value})
    }
    handleSubmit = (e)=>{
        e.preventDefault();
        console.log(this.state.val)
    }
    handleClick = ()=>{
        this.setState({val: 'vin'})
    }
    render(){
        return (
            <div>
                我是App元件
                <MyInput value={this.state.val} onChange={this.handleChange} onSubmit={this.handleSubmit}/>
                <button onClick={this.handleClick}>改變名字為 vin</button>
            </div>
        )
    }
}

2. 非受控元件

非受控元件的資料由表單DOM元素自己維護。
非受控元件中若想設定初始值,不能使用 value 屬性了,而是使用 defaultValue 屬性僅僅進行資料初始化。
通過為表單元素新增 ref 屬性的方式訪問表單內的資料。

<input defaultValue={x} ref={input}/>

class App extends React.Component{
    constructor(props){
        super(props)
        this.state = {val: ''}  
        this.myRef = React.createRef()
    } 
    handleSubmit = (e)=>{
        e.preventDefault();
        console.log(this.myRef.current.value)
    }
    render(){
        return (
            <div>
                我是App元件
                <form onSubmit={this.handleSubmit}>
                    <label>
                        名字:<input type="text" defaultValue={this.state.val} ref={this.myRef}/>
                    </label>
                    <label>
                        <input type="submit"/>
                    </label>
                </form>
            </div>
        )
    }
}