受控組件
當(dāng)input的狀態(tài)發(fā)生變化時,都會被組件寫入到組件的state中,這種組件在React中被稱為受阻控件。在受阻控件中,組件渲染出的狀態(tài)與它的value相對應(yīng)。
React通過這種方式消除了組件的局部狀態(tài),使得應(yīng)用的整個狀態(tài)更加可控。React受控組件更新state的流程:
- 可以通過在初始state中設(shè)置表單的默認值
- 每當(dāng)表單的值發(fā)生變化時,調(diào)用onChange事件處理器
- 事件處理器通過合成事件對象e拿到改變后的狀態(tài),并更新應(yīng)用的state
- setState觸發(fā)視圖的重新渲染,完成表單組件值的更新
以下示例,每當(dāng)往input框中輸入內(nèi)容,input的value屬性的值也會跟著相應(yīng)的做出改變。
import React, {Component} from 'react';
class Counter extends Component {
constructor(props) {
super(props)
this.handleClick = this.handleClick.bind(this)
this.state = {
value: '',
}
}
handleClick(e) {
this.setState({
value: e.target.value
})
}
render() {
return (
<div>
<input value={this.state.value} onChange={this.handleClick}/>
</div>
)
}
}
export default Counter
非受控組件
如果一個表單組件沒有value props時,就可以稱為非受控組件,相應(yīng)的,可以使用defaultValue和defaultChecked prop來表示組件的默認狀態(tài)。
在react中,非受控組件是一種反模式,它的值不受組件自身的state或props控制。通常需要通過為其添加ref prop來訪問渲染后的底層DOM元素。
import React, {Component} from 'react';
class Counter extends Component {
constructor(props) {
super(props)
this.handleSubmit = this.handleSubmit.bind(this)
}
handleSubmit(e) {
e.preventDefault()
const { value } = this.refs.name
console.log(value)
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<input ref="name" type="text" defaultValue="shanghai"/>
<button type="submit">Submit</button>
</form>
)
}
}
export default Counter
對比受控組件和非受控組件
- 性能上的問題
在受控組件中,每次表單的值發(fā)生變化時,都會調(diào)用一次onChange事件處理器,這確實會有一些性能上的消耗。雖然使用非受控組件不會出現(xiàn)這些問題,但仍然不提倡在React中使用非受控組件。這個問題可以通過Flux/Redux應(yīng)用架構(gòu)等方式來達到統(tǒng)一組件狀態(tài)的目的。 - 是否需要事件綁定
使用非受控組件,我們需要為每個組件綁定一個change事件,并且定義一個事件處理器來同步表單值和組件的狀態(tài),這是一個必要條件。當(dāng)然,在某些簡單的情況下,也可以使用一個事件處理器來處理多個表單域。