表單不同于其他 HTML 元素,因?yàn)樗憫?yīng)用戶的交互,顯示不同的狀態(tài),所以在 React 里面會(huì)有點(diǎn)特殊。
表單元素有這么幾種屬于狀態(tài)的屬性:
value
,對(duì)應(yīng) <input>
和 <textarea>
所有checked
,對(duì)應(yīng)類型為 checkbox
和 radio
的 <input>
所有selected
,對(duì)應(yīng) <option>
所有在 HTML 中 <textarea>
的值可以由子節(jié)點(diǎn)(文本)賦值,但是在 React 中,要用
value
來設(shè)置。
表單元素包含以上任意一種狀態(tài)屬性都支持 onChange
事件監(jiān)聽狀態(tài)值的更改。
針對(duì)這些狀態(tài)屬性不同的處理策略,表單元素在 React 里面有兩種表現(xiàn)形式。
對(duì)于設(shè)置了上面提到的對(duì)應(yīng)“狀態(tài)屬性“值的表單元素就是受控表單組件,比如:
render: function() {
return <input type="text" value="hello"/>;
}
一個(gè)受控的表單組件,它所有狀態(tài)屬性更改涉及 UI 的變更都由 React
來控制(狀態(tài)屬性綁定 UI)。比如上面代碼里的 <input>
輸入框,用戶輸入內(nèi)容,用戶輸入的內(nèi)容不會(huì)顯示(輸入框總是顯示狀態(tài)屬性 value
的值 hello
),這有點(diǎn)顛覆我們的認(rèn)知了,所以說這是受控組件,不是原來默認(rèn)的表單元素了。
如果你希望輸入的內(nèi)容反饋到輸入框,就要用 onChange
事件改變狀態(tài)屬性 value
的值:
getInitialState: function() {
return {value: 'hello'};
},
handleChange: function(event) {
this.setState({value: event.target.value});
},
render: function() {
var value = this.state.value;
return <input type="text" value={value} onChange={this.handleChange} />;
}
使用這種模式非常容易實(shí)現(xiàn)類似對(duì)用戶輸入的驗(yàn)證,或者對(duì)用戶交互做額外的處理,比如截?cái)嘧疃噍斎?40個(gè)字符:
handleChange: function(event) {
this.setState({value: event.target.value.substr(0, 140)});
}
和受控組件相對(duì),如果表單元素沒有設(shè)置自己的“狀態(tài)屬性”,或者屬性值設(shè)置為
null
,這時(shí)候就是非受控組件。
它的表現(xiàn)就符合普通的表單元素,正常響應(yīng)用戶的操作。
同樣,你也可以綁定 onChange
事件處理交互。
如果你想要給“狀態(tài)屬性”設(shè)置默認(rèn)值,就要用 React 提供的特殊屬性
defaultValue
,對(duì)于 checked
會(huì)有 defaultChecked
,<option>
也是使用 defaultValue
。
引入受控組件不是說它有什么好處,而是因?yàn)?React 的 UI 渲染機(jī)制,對(duì)于表單元素不得不引入這一特殊的處理方式。
在瀏覽器 DOM 里面是有區(qū)分 attribute 和 property 的。attribute 是在 HTML
里指定的屬性,而每個(gè) HTML 元素在 JS 對(duì)應(yīng)是一個(gè) DOM
節(jié)點(diǎn)對(duì)象,這個(gè)對(duì)象擁有的屬性就是 property(可以在 console 里展開一個(gè) DOM 節(jié)點(diǎn)對(duì)象看一下,HTML attributes 只是對(duì)應(yīng)其中的一部分屬性),attribute 對(duì)應(yīng)的 property 會(huì)從 attribute
拿到初始值,有些會(huì)有相同的名稱,但是有些名稱會(huì)不一樣,比如 attribute class
對(duì)應(yīng)的 property 就是
className
。(詳細(xì)解釋:.prop,.prop() vs
.attr())
回到 React 里的 <input>
輸入框,當(dāng)用戶輸入內(nèi)容的時(shí)候,輸入框的 value
property
會(huì)改變,但是 value
attribute 依然會(huì)是 HTML 上指定的值(attribute 要用
setAttribute
去更改)。
React 組件必須呈現(xiàn)這個(gè)組件的狀態(tài)視圖,這個(gè)視圖 HTML 是由 render
生成,所以對(duì)于
render: function() {
return <input type="text" value="hello"/>;
}
在任意時(shí)刻,這個(gè)視圖總是返回一個(gè)顯示 hello
的輸入框。
<select>
在 HTML 中 <select>
標(biāo)簽指定選中項(xiàng)都是通過對(duì)應(yīng) <option>
的 selected
屬性來做的,但是在 React 修改成統(tǒng)一使用 value
。
所以沒有一個(gè) selected
的狀態(tài)屬性。
<select value="B">
<option value="A">Apple</option>
<option value="B">Banana</option>
<option value="C">Cranberry</option>
</select>
你可以通過傳遞一個(gè)數(shù)組指定多個(gè)選中項(xiàng):<select multiple={true} value={['B', 'C']}>