1. 程式人生 > >React中文文件之Forms

React中文文件之Forms

Forms - 表單
在React中,HTML表單元素同其他DOM元素,有點不同。因為表單元素天生具備一些內部的state狀態。例如:下面的HTML表單接收一個名字:
		<form>
			Name:
			<input type="text" name="name" />
			<input type="submit" value="submit" />
		</form>
這個表單具有預設HTML表單的行為,當用戶提交表單,跳轉到新頁面。在React中,如果你想要這種行為,它預設就起作用。但是大多數情況,使用js函式來處理表單的提交,以及對使用者輸入的表單資料的訪問是很方便的。實現這個目的的標準方式是,使用一個叫做 'controlled components-控制組件' 技術


controlled components - 控制組件
在HTML中,表單元素,例如:<input> <textarea> 以及 <select> 典型的維護自己的state狀態,並且基於使用者的輸入而更新。在React中,多變的state狀態保持在 元件的state屬性中,並且只能通過 setState() 來更新。
我們可以通過 令React的state狀態變為 'single source of truth-但一來源?' 來結合兩種方式。之後,渲染表單的React元件,也可控制表單上隨後的使用者輸入。被React以這種方式控制的input表單元素,被稱為是:'controlled components-控制組件'。
例如,我們想實現之前的例子,當表單提交時,記錄name值,我們可以將表單寫作一個控制組件:
		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}>
						Name:
						<input type="text" value={this.state.value}>
						<input type="submit" value="Submit">
					</form>
				);
			}
		}

由於我們的表單元素設定了 'value' 屬性,展示的value值應該是 'this.state.value'來宣告React值的真實來源。由於每次敲擊鍵盤,會呼叫 'handleChange' 來更新React的state,當用戶輸入時,也會更新展示的值。
對於一個控制組件,每次狀態的改變都會引起一個相關的函式呼叫。這將直接修改或驗證使用者輸入。例如:如果我們想強制輸入的名字全部為大寫字母,我們可以如下定義 'handleChange':
		handleChange(event) {
			this.setState({value: event.target.value.toUpperCase()});
		}

textarea 標籤
在HTML中,'<textarea>' 元素如下定義,文字在它的內部:
		<textarea>
			Hello there, this is some text in a text area
		</textarea>
在React中,一個 '<textarea>' 使用 'value' 屬性來替代內部的文字。使用這種方法,'<textarea>' 表單元素,可以寫成一個 '行內單標籤' 形式:
		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}>
						Name:
						<textarea value={this.state.value} onChange={this.handleChange} />
						<input type="submit" value="submit">
					</form>
				);	
			}
		}

注意:'this.state.value' 在構造器中初始化,確保文字域剛開始有內部一些文字

select 標籤
在HTML中,'<select>' 建立一個下拉選單。例如,下面的HTML程式碼建立一個 'flavors' 的下拉列表:
		<select>
			<option value="grapefruit">Grapefruit</option>
			<option value="lime">Lime</option>
			<option selected value="coconut">Coconut</option>
			<option value="mango">Mango</option>
		</select>
注意:Coconut 選項是初始選中的,因為設定了 'selected' 屬性。React中國年,不使用 'selected' 屬性,而使用 'value' 屬性在 '<select>' 根標籤。在控制組件上,這會更加方便,因為你只需要在一個地方更新它的值。例如:
		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}>
						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>
						<input type="submit" value="Submit" />
					</form>
				);
			}
		}

總的來說,這使得 <input type="text">,<textarea>和<select> 所有都工作的非常相似-它們都接收一個 'value' 屬性,可以用來實現一個控制組件。


控制組件的供選方案
有時使用控制組件是乏味的,因為通過React元件,你需要對每一種資料改變方式寫一個事件處理,並管道傳遞(pipe)所有的輸入state狀態。這是極其厭煩的,當你將一個已經存在的程式碼轉變為React程式碼,或者使React應用和一個非React庫融合。在這些情況下,你可能想要尋求非控制組件(uncontrolled components),實現輸入表單的一種替代技術