React可以幫助管理應用中的狀態,自然也包括表單在內,現在知道React組件的核心理念就是可預知性和可測試性,在React中,表單組件有兩種類型:約束組件和無約束組件。
一、無約束組件
在HTML中表單組件與React組件的行爲方式並不一致,給定HTML的<input/>一個值,這個<input />的值仍是可以改變的。這正是無約束組件名稱的由來,因爲表單組件的值是不受約束的。
在React中這種行爲與設置<input />的default一致。我們可以通過defaultValue屬性設置<input/>的默認值。
var MyForm = React.createClass({
render:functin(){
return <input type ="text" defaultValue ="helloWorld!"/>;
}
});
上面這個例子展示的無約束組件。組件的value並非由父組件設置,而是讓<input />自己控制自己的值。
一個無約束組件沒有太大的用處,除非可以訪問它的值。因此需要給<input/>添加一個ref屬性,以訪問DOM節點的值。
ref是一個不屬於DOM屬性的特殊特殊屬性,用來標記DOM節點,可以通過this上下文訪問這個節點,爲了便於訪問,組件中所有的ref都添加到了this.refs上。
沒有設置value(或者設爲null)的<input>組件是一個不受限組件。對於不受限的<input>組件,渲染出來的元素直接反應用戶輸入。例如:
render:function(){
return<Input type="text"/>
}
以上代碼將是一個沒有任何內容過的空的輸入框,用戶輸入將理解反映到元素上。和受限元素一樣,使用onChange事件可以監聽值的變化。
如果想給組件設置一個非空的初始值,可以使用defaultValue屬性。例如:
render:function(){
return <input type="text" defaultValue="Hello" />;
}
以上代碼渲染出來的元素和受限組件一樣有一個初始化的值,但是這個值可以改變並反應到頁面上。
同樣的類型爲radio、checkbox、的<ingput>支持defaultChecked屬性,<select>支持defaultValue屬性。
render: function() {
return (
<div>
<input type="radio"name="opt" defaultChecked /> Option 1
<input type="radio"name="opt" /> Option 2
<select defaultValue="C">
<optionvalue="A">Apple</option>
<optionvalue="B">Banana</option>
<optionvalue="C">Cranberry</option>
</select>
</div>
);
}
二、約束組件
如果想要更好的控制表單組件,推薦使用約束組件。在約束組件中,輸入框的值是由父組件設置的。
var MyForm =React.createClass({
getInitialState:function(){
return{
helloTo:"hello World"
};
},
});
handleChange:funciton(){
this.setState({
helloTo:event.targer.value
});
},
submitHandler:function(){
event.preventDefault();
alert(this.state.helloTo);
},
render:funciton(){
return(
<form onSubmit ={this.submitHandler}>
<input type='text' value ={this.state.helloTo} onchange={this.handleChange} />
<br/>
<button type="submit">Speak</button>
</form>
);
}
});
這個顯著的變化是<input/>的值存儲在父組件中的state中,因此數據流有了清晰的定義:
getInitialState設置defaultValue
<input/>的值在渲染時被設置。
<input/>的值onChange時,change處理器被調用。
change處理器更新state
在重新渲染時更新<input/>的值
雖然與無約束組件相比,代碼量增加了不少但是現在可以控制數據流,在用戶輸入時更新state。
示例:
handleChange:function(event){
this.setState({
helloTo:event.target.value.toUpperCase()
});
}