表單是前端開(kāi)發(fā)中必不可少的組件,React作為前端框架,如果不能處理表單,就會(huì)被億萬(wàn)的前端工程師吐槽的。然而React對(duì)于表單的處理,還是有一些細(xì)節(jié)上的東西需要關(guān)注,接下來(lái)我們?cè)敿?xì)的描述在React中如何使用表單組件。
為了讓頁(yè)面效果美觀一點(diǎn),在頁(yè)面中引入bootstrap的css
npm install bootstrap --save
在react組件中引入外部css文件,直接可以使用import
import 'bootstrap/dist/css/bootstrap.css'
我們操作使用react,開(kāi)發(fā)中最多的內(nèi)容就是操作state中的數(shù)據(jù),那么進(jìn)行表單開(kāi)發(fā),就是要將表單中的數(shù)據(jù)與state中的數(shù)據(jù)關(guān)聯(lián)起來(lái),也就是說(shuō),當(dāng)用戶改變表單中的數(shù)據(jù)時(shí),state中的數(shù)據(jù)也會(huì)相應(yīng)的發(fā)生修改,當(dāng)state中的數(shù)據(jù)發(fā)生了修改,form中的數(shù)據(jù)也會(huì)進(jìn)行相應(yīng)的變化。這種變化,以Angularjs的雙向綁定最為著名,然而,react并沒(méi)有使用雙向綁定,而是使用了單向數(shù)據(jù)流。
單向數(shù)據(jù)流
在這里描述單向數(shù)據(jù)流,并不采用一些比較正規(guī)的說(shuō)法,我所說(shuō)的是在開(kāi)發(fā)中的直觀感受。在前端開(kāi)發(fā)過(guò)程中,數(shù)據(jù)最終展示在頁(yè)面中,需要經(jīng)過(guò)一個(gè)渲染過(guò)程,即改變?yōu)g覽器頁(yè)面中的DOM結(jié)構(gòu)或者DOM中的內(nèi)容,從而瀏覽器進(jìn)行了解析渲染,如果要開(kāi)發(fā)人員手動(dòng)寫(xiě)原生的JS代碼操作DOM,在開(kāi)發(fā)復(fù)雜應(yīng)用時(shí),那將是一個(gè)極其痛苦的過(guò)程。單向數(shù)據(jù)流的作用就是,當(dāng)內(nèi)存中的數(shù)據(jù)發(fā)生變化時(shí),在頁(yè)面的相應(yīng)位置上,會(huì)自動(dòng)的渲染這些數(shù)據(jù),這就意味著開(kāi)發(fā)人員不再寫(xiě)DOM操作的代碼。
所謂單向數(shù)據(jù)流,意味著數(shù)據(jù)從一個(gè)地方流向另一個(gè)地方,即從瀏覽器內(nèi)存 到 頁(yè)面DOM樹(shù)

這就是react的強(qiáng)大之處,同時(shí)也是其短板之處,從內(nèi)存到DOM,可以自動(dòng)渲染,但是從DOM到內(nèi)存,就需要開(kāi)發(fā)人員手動(dòng)處理。
創(chuàng)建表單
import React from 'react';
import 'bootstrap/dist/css/bootstrap.css'
class App extends React.Component{
constructor(props){
super(props);
this.state = {
name:''
};
}
render(){
return (
<div className="container" style={{marginTop:'20px'}}>
<div className="row">
<div className="col-md-5">
<form className="form-horizontal">
<div className="form-group">
<label className="col-sm-2 control-label">用戶名</label>
<div className="col-sm-10">
<input type="email" className="form-control" id="name" name="name" placeholder="用戶名" />
</div>
</div>
</form>
</div>
</div>
</div>
);
}
}
export default App;
此時(shí)的表單中,其內(nèi)部數(shù)據(jù)的狀態(tài)由其自身維持,當(dāng)用戶在表單中進(jìn)行輸入時(shí),表單的數(shù)據(jù)狀態(tài)發(fā)生了變化,但是state中的狀態(tài)仍然保持原狀態(tài),React只對(duì)表單組件進(jìn)行了渲染,但并未控制其后續(xù)輸入的變化,我們稱此時(shí)的表單組件為非受控組件。
讓React渲染表單組件,組件中的值由React賦予,并控制其因用戶輸入所帶來(lái)的變化,即讓表單組件成為受控組件
- 表單組件的value值由React進(jìn)行初始化
<input type="text" className="form-control" id="name" value={this.state.name} name="name" placeholder="用戶名" onChange={this.handleChange}/>
- 監(jiān)聽(tīng)組件change事件,將其變化的值修改保存到state中
handleChange = (event) =>{
this.setState({
[event.target.name]:event.target.value
});
}
對(duì)于text,textarea,上述的方式均可,radio由于是單選,所以仍舊可以按照text的方式進(jìn)行處理,但是對(duì)于checkbox,就需要做特殊的處理了
<div className="form-group">
<label className="col-sm-2 control-label">愛(ài)好</label>
<div className="col-sm-10">
<div className="checkbox">
<label>
<input type="checkbox" name="hobby" value="1"/>音樂(lè)
</label>
</div>
<div className="checkbox">
<label>
<input type="checkbox" name="hobby" value="2"/>美術(shù)
</label>
</div>
<div className="checkbox">
<label>
<input type="checkbox" name="hobby" value="3"/>體操
</label>
</div>
</div>
</div>
checkbox組件為多選,所以,state中就需要使用數(shù)組來(lái)存儲(chǔ)數(shù)據(jù)
- 使用onChange事件控制組件
- 修改state屬性,要根據(jù)組件的
checked屬性來(lái)判斷
3.設(shè)置組件中的checked的值,需要根據(jù)state中的數(shù)據(jù)進(jìn)行判斷
- 初始化state
constructor(props){
super(props);
this.state = {
music:false,
draw:false,
gymnastics:false
};
}
- 為組件綁定
onChange并對(duì)其checked進(jìn)行判斷
<div className="form-group">
<label className="col-sm-2 control-label">愛(ài)好</label>
<div className="col-sm-10">
<div className="checkbox">
<label>
<input type="checkbox" name="music" checked={this.state.music} onChange={this.handleChange}/>音樂(lè)
</label>
</div>
<div className="checkbox">
<label>
<input type="checkbox" name="draw" checked={this.state.draw} onChange={this.handleChange}/>美術(shù)
</label>
</div>
<div className="checkbox">
<label>
<input type="checkbox" name="gymnastics" checked={this.state.gymnastics} onChange={this.handleChange}/>體操
</label>
</div>
</div>
</div>
- 在onChange函數(shù)中進(jìn)行數(shù)據(jù)處理
handleChange = (event) =>{
var temp = {
[event.target.name]:event.target.checked
};
this.setState(temp);
}
列表
現(xiàn)在業(yè)內(nèi)流行的前端框架對(duì)于列表循環(huán)的支持,可以說(shuō)是解放了廣大 前端開(kāi)發(fā)人員,從前的jquery瘋狂拼接字符串,到后來(lái)使用一些插件,而現(xiàn)在,一切變得很簡(jiǎn)單
1.定義一組數(shù)組
const users = [{
id:1,
name:'張三',
age:10
},{
id:2,
name:'李四',
age:10
},{
id:3,
name:'王五',
age:10
},{
id:4,
name:'趙六',
age:10
}];
2.在render函數(shù)中首先根據(jù)數(shù)組生成列表組件
const tbodys = users.map((user)=>{
return (
<tr key={user.id}>
<td>{user.id}</td>
<td>{user.name}</td>
<td>{user.age}</td>
</tr>
)
});
tbodys就是一個(gè)我們需要的列表組件,然后將其添加到render函數(shù)中返回的結(jié)構(gòu)中
return (
<div className="container" style={{marginTop:'30px'}}>
<div className="row">
<div className="col-md-8 col-md-offset-2">
<table className="table table-bordered">
<thead>
<tr>
<th>id</th>
<th>名稱</th>
<th>年齡</th>
</tr>
</thead>
<tbody>
{tbodys}
</tbody>
</table>
</div>
</div>
</div>
);
此時(shí)就得到一個(gè)完美的列表

返回值得結(jié)構(gòu)中的組件與前面使用map函數(shù)的遍歷結(jié)構(gòu)是等價(jià)的,因此,我們可以直接JSX中使用map函數(shù)遍歷
render() {
return (
<div className="container" style={{marginTop:'30px'}}>
<div className="row">
<div className="col-md-8 col-md-offset-2">
<table className="table table-bordered">
<thead>
<tr>
<th>id</th>
<th>名稱</th>
<th>年齡</th>
</tr>
</thead>
<tbody>
{
users.map((user)=>{
return (
<tr key={user.id}>
<td>{user.id}</td>
<td>{user.name}</td>
<td>{user.age}</td>
</tr>
)
})
}
</tbody>
</table>
</div>
</div>
</div>
);
}
寫(xiě)到這里呢,React從零開(kāi)始系 學(xué)習(xí)的系列就要結(jié)束了
之后我要重新回歸java的學(xué)習(xí)中了!