表單
在 React 中颅湘,HTML 表單元素和其它的 DOM 元素有一點(diǎn)不同簸喂,因?yàn)楸韱卧靥焐谋3忠恍﹥?nèi)部狀態(tài)吗伤。例如珠移,這個(gè)普通的 HTML 表單接收一個(gè)單一的 name:
<form>
<label>
Name:
<input type="text" name="name" />
</label>
<input type="submit" value="Submit" />
</form>
這個(gè)表單有默認(rèn)的 HTML 表單行為茁裙,當(dāng)用戶提交表單時(shí)喝峦,會(huì)跳轉(zhuǎn)到新的頁面。如果你想在 React 中有這個(gè)行為呜达,它也是有效的谣蠢。但是大多數(shù)情況下,讓一個(gè) JavaScript 函數(shù)來處理表單的提交和訪問用戶輸入的數(shù)據(jù)是比較方便的查近。實(shí)現(xiàn)這個(gè)效果的標(biāo)準(zhǔn)方式是使用稱為“受控組件”的技術(shù)眉踱。
受控組件
在 HTML 中,表單元素如<input>
霜威、<textarea>
和<select>
通程冈基于用戶的輸入維護(hù)或更新自身的狀態(tài)。在 React 中戈泼,可變的狀態(tài)通常保存在組件的 state 屬性婿禽,并且只能使用setState()
來更新。
我們可以通過使 React state 成為“單一數(shù)據(jù)源”來使兩者結(jié)合大猛。然后 React 組件渲染一個(gè)表單并控制這個(gè)表單在隨后的用戶輸入中發(fā)生了什么扭倾。用這種方法被 React 控制 value 的 input 表單元素被稱為“受控組件”。
例如挽绩,我們想使之前的例子在提交的時(shí)候顯示輸入的 name膛壹,我們把這個(gè)表單寫成受控組件:
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('A name was submitted: ' + this.state.value);
event.preventDefault();
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
Name:
<input type="text" value={this.state.value} onChange={this.handleChange} />
</label>
<input type="submit" value="Submit" />
</form>
);
}
}
在CodePen上試試。
由于我們的表單設(shè)置了value
屬性,value 的顯示一直會(huì)是this.state.value
的值模聋,使 React state 成為單一數(shù)據(jù)源肩民。由于每次輸入都會(huì)運(yùn)行handleChange
來更新 React state,用戶的輸入會(huì)作為 value 的更新顯示链方。
使用一個(gè)受控組件持痰,每一個(gè) state 的變化都會(huì)有一個(gè)與之相關(guān)聯(lián)的處理函數(shù)。這使得修改或驗(yàn)證用戶的輸入變得更簡單明確祟蚀。例如工窍,我們想讓用戶的輸入強(qiáng)制變成大寫,我們可以把handleChange
寫成這樣:
handleChange(event) {
this.setState({value: event.target.value.toUpperCase()});
}
textarea 標(biāo)簽
在 HTML 中暂题,<textarea>
元素通過它的子元素定義它的文本:
<textarea>
Hello there, this is some text in a text area
</textarea>
在 React 中<textarea>
使用一個(gè)value
屬性代替。這種方式究珊,textarea
表單的編寫和編寫單行 input 表單非常類似:
class EssayForm extends React.Component {
constructor(props) {
super(props);
this.state = {
value: 'Please write an essay about your favorite DOM element.'
};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(event) {
this.setState({value: event.target.value});
}
handleSubmit(event) {
alert('An essay was submitted: ' + this.state.value);
event.preventDefault();
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
Name:
<textarea value={this.state.value} onChange={this.handleChange} />
</label>
<input type="submit" value="Submit" />
</form>
);
}
}
注意薪者,this.state.value
是在構(gòu)造函數(shù)中初始化的,所以文本域一開始就有一些文本在里面剿涮。
select 標(biāo)簽
在 HTML 中言津,<select>
創(chuàng)建一個(gè)下拉列表。例如取试,這段 HTML 代碼創(chuàng)建了一個(gè)關(guān)于風(fēng)味的下拉列表:
<select>
<option value="grapefruit">Grapefruit</option>
<option value="lime">Lime</option>
<option selected value="coconut">Coconut</option>
<option value="mango">Mango</option>
</select>
注意悬槽,由于selected
屬性,Coconut 選項(xiàng)是被默認(rèn)選擇的瞬浓。React 不使用selected
屬性初婆,而是在select
標(biāo)簽根上使用value
屬性。這在一個(gè)受控組件中更方便猿棉,因?yàn)槟銉H需在一個(gè)地方更新它磅叛。例如:
class FlavorForm extends React.Component {
constructor(props) {
super(props);
this.state = {value: 'coconut'};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(event) {
this.setState({value: event.target.value});
}
handleSubmit(event) {
alert('Your favorite flavor is: ' + this.state.value);
event.preventDefault();
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
Pick your favorite La Croix flavor:
<select value={this.state.value} onChange={this.handleChange}>
<option value="grapefruit">Grapefruit</option>
<option value="lime">Lime</option>
<option value="coconut">Coconut</option>
<option value="mango">Mango</option>
</select>
</label>
<input type="submit" value="Submit" />
</form>
);
}
}
在CodePen上試試。
總的來說萨赁,這使得<input type="text">
弊琴、<textarea>
和<select>
工作方式非常相似——它們都接收一個(gè)value
屬性,你可以使用它來實(shí)現(xiàn)一個(gè)受控組件杖爽。
替代受控組件
有時(shí)使用受控組件是乏味的敲董,因?yàn)槟阈枰ㄟ^一個(gè)組件為所有的數(shù)據(jù)變化的方式和管道處理所有的輸入 state 編寫事件處理器。當(dāng)你轉(zhuǎn)換一個(gè)已存在的代碼庫到 React慰安,或使用非 React 庫整合一個(gè) React 應(yīng)用時(shí)腋寨,這一點(diǎn)尤為惱人。在這種情況下化焕,你可能想查看非受控組件精置,一個(gè)實(shí)現(xiàn) input 表單的另類技術(shù)。
下一步
提升 State