受控元件 VS 非受控元件
阿新 • • 發佈:2020-08-17
寫在前面
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>
)
}
}