React官方文件--Forms
Forms
表單元件,比如:<input>
,<textarea>
和<option>
和基本的元件不同,因為表單元件是需要使用者進行互動的。這些元件提供了介面,用來更容易的管理表單來響應使用者的互動。
有兩種形式的表單元件
1. Controlled Components
2. Uncontrolled Components
Controlled Components
一個受控表單元件提供一個value
屬性,一個受控表單元件不會維持其內部自己的狀態,元件只根據props進行渲染。
render() {
return (
<input
type ="text"
value="Hello!"
/>
)
}
如果你試圖去執行這裡例子,會發現輸入框裡的內容不會隨著輸入而改變。因為你聲明瞭這個元件的value值,為了更新value作為使用者輸入的響應,需要新增onChange事件來儲存新的值,然後傳遞這個值給value屬性。
class Form 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) {
console.log("Text field value is : " + this.state.value);
}
render() {
return (
<div>
<input type="text" placeholder="Hello!"
value={this.state.value} onChange={this.handleChange}/>
<button onClick={this.handleSubmit}>
Submit
</button>
</div>
)
}
}
ReactDOM.render(
<Form />,
document.getElementById("root")
);
在這個例子中,我們接受使用者提供的值,來更新value 的值,這種方法使得繼承介面或者進行表單驗證變得很方便
handleChange(event) {
this.setState({
value: event.target.value.substr(0, 14)
});
}
Checkboxes和RadioButton存在的潛在問題
在使用React來監聽checkbox或者radio的事件的時候,React監聽一個click的瀏覽器事件來宣告一個onChange事件,在大部分情況下這樣是沒有什麼問題的,除非當你呼叫了preventDefault()
在change的事件處理函式裡面,preventDefault會停止瀏覽器在視覺上更新輸入,即使checked的值已經改變了,這個問題可以通過不呼叫preventDefault或者將切換checked的值放在setTimeout中執行來解決。
非受控元件
不提供value屬性的表單元件稱為非受控元件。下面的例子渲染了一個<input>
來控制一個空的值,任何使用者輸入的值會立刻影響到渲染的元素。
一個非受控元件管理他自己的狀態。
render() {
return <input type="text" />
}
如果你希望監聽這個元件的值的更新,你需要使用onChange
事件來監聽,就像受控元件一樣,但是不能給元件傳遞任何值。
class Form 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("Text field value is : " + this.state.value);
}
render() {
return (
<div>
<input
type="text"
placeholder="Hello!"
onChange={this.handleChange} />
<button onClick={this.handleSubmit}>
Submit
</button>
</div>
);
}
}
ReactDOM.render(
<Form />,
document.getElementById("root")
)
當這個例子輸入value的時候,我們可以通過handleSubmit()
來讀取,非受控表單元件不能夠請求,你需要完整的onChange
事件處理來取代讀取value
。
預設值
使用一個非空的value
來初始化一個非受控元件,你可以使用一個defaultValue
屬性
render() {
return <input type="text" defaultValue="Hello" />
}
同樣地,<input type="checkbox">
和<input type="radio">
支援defaultChecked
然後<select>
支援defaultValue
。
互動屬性
表單元件支援一系列的props會通過使用者互動影響元件。
1. value
,是<input>
和<textarea>
支援的元件。
2. checked
,是<input>
元件的checkbox
和radio
支援的
3. selected
,是<option>
元件支援的。
在HTML中,<textarea>
的值是通過子元素來設定的,在React中,需要使用value
來替代
表單元件允許通過onChange
屬性的回撥函式來監聽修改,onChange
屬性通過瀏覽器和使用者互動的響應。
進階技術
為什麼使用受控元件
使用類似<input>
的表單元件是和傳統的HTML不相同的。
<input type="text" name="title" value="Untitle">
上面的程式碼渲染初始化了一個value為Untitle。當用戶更新輸入的時候,這個節點的value屬性也會改變,然而使用node.getAttribute('value')
仍然會返回初始化的時候的值:Untitled
。
與HTML不同的是,React元件必須一致保持其狀態,也就是自從渲染之後,value
的值一直保持為Untitled
。
Why Textarea Value
在HTML,<textarea>
的值應該是其子元素的值。
<textarea name="description">This is the description.</textarea>
在HTML中,很容易允許開發人員提供多行的值,然而,在React中,我們不能夠設定多行的字串,如果要換行的話需要使用\n
,在有value和defaultValue的時候,因為這個原因,你不需要使用子元素來設定<textarea>
的值。
<textarea name="description" value="This is a description.">
Why Select Value
option
在<select>
中是用selected
屬性來進行判斷選擇的,但是在React的元件中,是使用value
屬性的。
<select value="B">
<option value="A">Apple</option>
<option value="B">Banana</option>
<option value="C">Cranberry</option>
</select>
使用非受控元件的話,這裡需要使用defaultValue
受控輸入框
class Form 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('Text field value is: ' + this.state.value);
}
render() {
return (
<div>
<input
type="text"
placeholder="edit me"
value={this.state.value}
onChange={this.handleChange}
/>
<button onClick={this.handleSubmit}>
Submit
</button>
</div>
);
}
}
ReactDOM.render(
<Form />,
document.getElementById('root')
);
受控文字區元件
class Form 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("Textarea value is: " + this.state.value);
}
render() {
return (
<div>
<textarea
name="description"
value={this.state.value}
onChange={this.handleChange}
/>
<br/>
<button onClick={this.handleSubmit}>
Submit
</button>
</div>
)
}
}
ReactDOM.render(
<Form />,
document.getElementById("root")
);
受控下拉列表
class Form 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("Select value is: " + this.state.value);
}
render() {
return (
<div>
<select value={this.state.value} onChange={this.handleChange}>
<option value="A">Apple</option>
<option value="B">Banana</option>
<option value="C">Cranberry</option>
</select>
<br/>
<button onClick={this.handleSubmit}>
Submit
</button>
</div>
)
}
}
ReactDOM.render(
<Form />,
document.getElementById("root")
);
非受控單選按鈕
class Form extends React.Component {
constructor(props) {
super(props);
this.state = {
value: "B"
}
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(event) {
this.setState({
value: event.target.value
});
}
handleSubmit(event) {
alert("Radio button value is: " + this.state.value);
}
render() {
return (
<div>
<label>
<input type="radio" name="choice" value="A" onChange={this.handleChange}/>
Option A
</label>
<label>
<input type="radio" name="choice" value="B" onChange={this.handleChange}/>
Option B
</label>
<label>
<input type="radio" defaultChecked={true} name="choice" value="C" onChange={this.handleChange}/>
Option C
</label>
<br/>
<button onClick={this.handleSubmit}>
Submit
</button>
</div>
)
}
}
ReactDOM.render(
<Form />,
document.getElementById("root")
);
非受控複選框
class Form extends React.Component {
constructor(props) {
super(props);
this.state = {
checked: {
'A': false,
'B': true,
'C': false
}
};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(event) {
const value = event.target.value;
const checked = Object.assign({}, this.state.checked);
if (!checked[value]) {
checked[value] = true;
} else {
checked[value] = false;
}
this.setState({checked});
}
handleSubmit(event) {
alert("Boxes checked: " +
(this.state.checked.A ? 'A ' : ' ') +
(this.state.checked.B ? 'B ' : ' ') +
(this.state.checked.C ? 'C ' : ' ')
);
}
render() {
return (
<div>
<label>
<input type="checkbox" value="A" onChange={this.handleChange} />
Option A
</label>
<label>
<input type="checkbox" value="B" onChange={this.handleChange} defaultChecked={true}/>
Option B
</label>
<label>
<input type="checkbox" value="C" onChange={this.handleChange} />
Option C
</label>
<button onClick={this.handleSubmit}>
Submit
</button>
</div>
)
}
}
ReactDOM.render(
<Form />,
document.getElementById("root")
);