在 HTML 中氯哮,表單元素(如
<input>
、<textarea>
和<select>
)之類(lèi)的表單元素通常自己維護(hù) state扫腺,并根據(jù)用戶(hù)輸入進(jìn)行更新愁茁。而在 React 中蚕钦,可變狀態(tài)(mutable state)通常保存在組件的 state 屬性中,并且只能通過(guò)使用setState()
來(lái)更新鹅很。
我們可以把兩者結(jié)合起來(lái)嘶居,使 React 的 state 成為“唯一數(shù)據(jù)源”。渲染表單的 React 組件還控制著用戶(hù)輸入過(guò)程中表單發(fā)生的操作促煮。被 React 以這種方式控制取值的表單輸入元素就叫做“受控組件”邮屁。
寫(xiě)一個(gè)普通表單:
<form>
<label>
名字:
<input type="text" name="name" />
</label>
<input type="submit" value="提交" />
</form>
將表單寫(xiě)為受控組件,我們可以在提交時(shí)打印出名稱(chēng)等操作:
class NameForm extends React.Component {
constructor(props) {
super(props);
this.state = {value: ''};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(event) {
this.setState({value: event.target.value});
}
handleSubmit(event) {
alert('提交的名字: ' + this.state.value);
event.preventDefault(); // 阻止表單提交的默認(rèn)事件
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
名字:
<input type="text" value={this.state.value} onChange={this.handleChange} />
</label>
<input type="submit" value="提交" />
</form>
);
}
}
由于在表單元素上設(shè)置了 value 屬性菠齿,因此顯示的值將始終為 this.state.value佑吝,這使得 React 的 state 成為唯一數(shù)據(jù)源。由于 handlechange 在每次按鍵時(shí)都會(huì)執(zhí)行并更新 React 的 state绳匀,因此顯示的值將隨著用戶(hù)輸入而更新芋忿。
對(duì)于受控組件來(lái)說(shuō)炸客,輸入的值始終由 React 的 state 驅(qū)動(dòng)。
其它標(biāo)簽實(shí)現(xiàn)受控組件
<input type="text">
, <textarea>
和 <select>
之類(lèi)的標(biāo)簽都非常相似—它們都接受一個(gè) value 屬性戈钢,你可以使用它來(lái)實(shí)現(xiàn)受控組件痹仙。
textarea
<form onSubmit={this.handleSubmit}>
<label>
文章:
<textarea value={this.state.value} onChange={this.handleChange} />
</label>
<input type="submit" value="提交" />
</form>
select
<form onSubmit={this.handleSubmit}>
<label>
選擇你喜歡的風(fēng)味:
<select value={this.state.value} onChange={this.handleChange}>
<option value="grapefruit">葡萄柚</option>
<option value="lime">酸橙</option>
<option value="coconut">椰子</option>
<option value="mango">芒果</option>
</select>
</label>
<input type="submit" value="提交" />
</form>
處理多個(gè)輸入
當(dāng)需要處理多個(gè) input 元素時(shí),我們可以給每個(gè)元素添加 name 屬性殉了,并讓處理函數(shù)根據(jù) event.target.name 的值選擇要執(zhí)行的操作开仰。
例如:
handleInputChange(event) {
const target = event.target;
const value = target.name === 'isGoing' ? target.checked : target.value;
const name = target.name;
this.setState({
[name]: value
});
}
render() {
return (
<form>
<label>
參與:
<input
name="isGoing"
type="checkbox"
checked={this.state.isGoing}
onChange={this.handleInputChange} />
</label>
<br />
<label>
來(lái)賓人數(shù):
<input
name="numberOfGuests"
type="number"
value={this.state.numberOfGuests}
onChange={this.handleInputChange} />
</label>
</form>
);
}
受控輸入空值
在受控組件上指定 value 的 prop 會(huì)阻止用戶(hù)更改輸入。如果你指定了 value
宣渗,但輸入仍可編輯抖所,則可能是你意外地將value
設(shè)置為 undefined
或 null
。
下面的代碼演示了這一點(diǎn)痕囱。(輸入最初被鎖定田轧,但在短時(shí)間延遲后變?yōu)榭删庉嫛#?/p>
// 指定value的值為'hi'的時(shí)候輸入框不可編輯
ReactDOM.render(<input value="hi" />, mountNode);
setTimeout(function() {
ReactDOM.render(<input value={null} />, mountNode);
}, 1000);
受控組件的替代品
有時(shí)使用受控組件會(huì)很麻煩鞍恢,因?yàn)槟阈枰獮閿?shù)據(jù)變化的每種方式都編寫(xiě)事件處理函數(shù)傻粘,并通過(guò)一個(gè) React 組件傳遞所有的輸入 state。在這些情況下帮掉,你可能希望使用非受控組件(ref), 這是實(shí)現(xiàn)輸入表單的另一種方式弦悉。