React(6)React受控元件的使用
技術標籤:Reactreactjavascript
文章目錄
前言
在一個實際的專案中,表單是必不可少的DOM元素。專案中出現的表單元素,React要如何獲取使用者在表單元素中書寫或選擇的內容呢?本篇文章就為大家講解React中受控元件的使用方法。
受控元件:Controlled Component,元件的資料受到state元件狀態的控制,我們將這類元件稱為“受控元件”。受控元件在使用時要實現元件資料和state元件狀態的雙向繫結。
一、文字類表單元素的受控控使用方法
文字類表單元素包括文字域、密碼域、多行文字域三種表單元素。它們使用value屬性來繫結表單元素的預設值,同時使用onChange事件編寫當文字內容發生變化時所執行的程式碼。我們將這種用法稱為“value-onChange”組合。
例1:在頁面中有一個用於輸入暱稱的表單元素和一個按鈕。使用者在文字框中輸入自己的暱稱,單擊按鈕後獲取使用者輸入的暱稱內容,並在控制檯中顯示。
class App extends React.Component {
constructor(props){
super(props);
this.state= {
nick:""
}
}
render(){
return (
<React.Fragment>
<label htmlFor="nick">暱稱</label>
<input type="text" id="nick" value={this.state.nick} onChange={(event)=>{this.nickChange(event)}} />
< div><button onClick={()=>this.getNick()}>獲取暱稱</button></div>
</React.Fragment>
)
}
}
從上述程式碼中可以看出,文字框利用value屬性綁定了state區的nick資料作為文字框的預設值,即空字串。同時又為文字框綁定了onChange事件。該事件只需要將文字框中使用者輸入的內容賦值給state區的nick資料即可。文字框中使用者輸入的內容可以使用onChange事件函式中的event.tarvar.value獲取。
文字框的onChange事件程式碼如下所示。
onChange(event){
this.setState({
nick:event.target.value
})
}
按鈕的單擊事件程式碼如下所示。
getNick(){
console.log(this.state.nick);
}
從例1中可以看出,文字框中的value屬性只能為文字框繫結一個初始值,當文字框中的文字內容發生變化時,還需要藉助onChange事件來將文字框的值賦給value屬性當初繫結的state資料。
例2:在頁面中有一個用於輸入留言的多行文字域和一個按鈕。使用者在多行文字框中輸入留言文字,單擊按鈕後獲取使用者輸入的留言內容,並在控制檯中顯示。同時隨著使用者輸入文字的增多,在頁面中顯示已經輸入了多少個字元,同時限制最多輸入20個字元。
效果圖如下所示。
class App extends React.Component {
constructor(props){
super(props);
this.state={
message:"",
inputed:0,
total:20
}
}
render(){
return (
<React.Fragment>
<label htmlFor="message">留言:(已輸入{this.state.inputed}/{this.state.total})</label>
<textarea id="message" value={this.state.message} onChange={(event)=>{this.messageChange(event)}></textarea>
<div><button onClick={()=>this.submitMessage()}>提交留言</button></div>
</React.Fragment>
)
}
}
多行文字域的處理方式和文字域的處理方式相同,都是採用value-onChange組合來實現的。當用戶在多行文字域中輸入內容時,將觸發onChange事件,該事件程式碼如下所示。
messageChange(event){
let message=event.target.value;
this.setState({
inputed:message.length
})
if(this.state.inputed<this.state.total-1){
this.setState({
message
})
}
}
按鈕的單擊事件程式碼如下所示。
submitMessage(){
console.log(this.state.message);
}
在state區中,message資料用來接收使用者在多行文字域中輸入的內容,inputed資料用來記錄已經輸入的文字個數,total資料用來指定最多能夠輸入的文字個數。
二、單選框的受控使用方法
單選框在使用時繼續延續文字框和多行文字框的使用方式,唯一不同的是單選框採用的是checked-onChange組合來實現受控操作的。
例3:在頁面中有一組用於選擇性別的單選框和一個按鈕。使用者選擇了某個單選項之後,單擊按鈕獲取使用者所選單選項的內容,並在控制檯中顯示。
class App extends Component{
constructor(props){
super(props);
this.state={
sex:'男'
}
}
render(){
return (
<React.Fragment>
<label>性別:</label>
<input type="radio" value="男" checked={this.state.sex==="男"} onChange={(event)=>this.radioChange(event)} /> 男
<input type="radio" value="女" checked={this.state.sex==="女"} onChange={(event)=>this.radioChange(event)} /> 女
<div><button onClick={()=>this.getSex()}>所選性別</button></div>
</React.Fragment>
)
}
}
在上述程式碼中,每一個單選框同樣具備了value屬性,但是這個value屬性已經和文字框的value屬性不一樣了,這個value屬性為單選框被選中後提供了與其他單選框所不同的資料。checked屬性取值為邏輯值,因此繫結的是this.state.sex是不是和指定的取值相等,相等則為true,不相等則為false。
單選框的onChange事件程式碼如下所示。
radioChange(event){
this.setState({
sex:event.target.value
})
}
按鈕的單擊事件程式碼如下所示。
getSex(){
console.log(this.state.sex);
}
程式碼中通過checked屬性中的判斷來獲取哪一個單選項預設被選中,再借助onChange事件改變state區的sex資料,以實現checked屬性和sex資料的雙向繫結。
三、複選框的受控使用方法
複選框和單選框一樣,也是用checked-onChange組合來對其進行操作,但是複選框可以選中多個複選項,而單選框只能選擇一個,因此複選框的checked屬性一應該繫結的是一個數組。
例4:在頁面中有一組用於選擇愛好的複選框和一個按鈕。使用者選擇了某些複選項之後,單擊按鈕獲取使用者所選複選項的內容,並在控制檯中顯示。
效果圖如下所示。
class App extends Component{
constructor(props){
super(props);
this.state={
favs:["音樂","電影","遊戲","跑步","游泳","讀書"],
fav:["電影"]
}
}
render(){
return (
<React.Fragment>
<label>愛好:</label>
{
this.state.favs.map((item,index)=>{
return (
<span key={index}>
<input type="checkbox" value={item} checked={this.state.fav.includes(item)} onChange={(event)=>this.checkboxChange(event)} /> {item}
</span>
)
})
}
<div><button onClick={()=>this.getFav()}>所選愛好</button></div>
</React.Fragment>
)
}
}
在上述程式碼中,state區定義了兩個資料:favs作為陣列提供所有備選的愛好內容,fav作為陣列用來儲存使用者選擇的愛好內容。
- 複選框是由state區的favs進行遍歷來實現的。
- 複選框的checked屬性取值為邏輯值,繫結的資料是判斷favs陣列元素item是否在fav陣列中,即fav陣列中是否包含favs的陣列元素item。這裡採用的是ES6為陣列新增的includes()方法,該方法直接返回引數是否包含在指定的數值中的邏輯值。
複選框的onChange事件程式碼如下所示。
checkboxChange(event){
let temp=event.target.value; //使用者選中的那一個複選框的value屬性
let fav=[...this.state.fav];
let index=fav.findIndex(item=>item===temp);
if(index!==-1){
//單擊該複選框時,該複選框的value屬性取值在fav陣列中存在
fav.splice(index,1);
}else{
//單擊該複選框時,該複選框的value屬性取值在fav陣列中不存在
fav.push(temp);
}
this.setState({fav});
}
按鈕的單擊事件程式碼如下所示。
getFav(){
console.log(this.state.fav)
}
該案例涉及到了大量的陣列與陣列元素之間的操作。雖然同樣使用checked-onChange組合來完成,但是兩個陣列favs和fav之間要進行大量的判斷,才能完成最終的效果。
四、選單的受控使用方法
<select>選單在表單元素中表示下拉選單,是一個單選元素,同樣使用value-onChange組合來進行處理。
例5:在頁面中有一組用於選擇專業的下拉選單和一個按鈕。使用者選擇了某個專業之後,單擊按鈕獲取使用者所選專業的內容,並在控制檯中顯示。
class App extends Component{
constructor(props){
super(props);
this.state={
specs:["前端開發","PHP開發","Java開發","UI設計","大資料開發","人工智慧"],
spec:"前端開發"
}
}
render(){
return (
<React.Fragment>
<label>專業:</label>
<select value={this.state.spec} onChange={(event)=>this.specChange(event)}>
{
this.state.specs.map((item,index)=>{
return <option value={item} key={index}>{item}</option>
})
}
</select>
<div><button onClick={()=>this.getSpec()}>所選專業</button></div>
</React.Fragment>
)
}
}
在上述程式碼中,state區定義了兩個資料:specs作為陣列提供所有備選的專業內容,spec用來儲存使用者選擇的專業內容,因為是單選,因此資料型別為字串。
- 下拉選單的選單項(即<option>標記)是由state區的specs進行遍歷來實現的。
- 由於下拉選單項具備容器(即<select>標記),因此<select>標記的value屬性用來繫結state區的spec資料,作為預設選中項。
- <option>的value屬性而是為下拉選單項設定被選中後的取值。
下拉選單的onChange事件程式碼如下所示。
specChange(event){
this.setState({
spec:event.target.value
})
}
按鈕的單擊事件程式碼如下所示。
getSpec(){
console.log(this.state.spec)
}
仔細分析,下拉選單的處理方式本質上和文字框是完全相同的。
五、列表的受控使用方法
<select>列表在表單元素中表示列表選擇框,是一個可以複選的元素,同樣使用value-onChange組合來進行處理。
例6:在頁面中有一組用於選擇選修課程的下拉列表和一個按鈕。使用者選擇了某些選修課程後,單擊按鈕獲取使用者所選的選修課程內容,並在控制檯中顯示。
效果圖如下所示。
class App extends Component{
constructor(props){
super(props);
this.state={
courses:["高等數學","線性代數","概率統計","離散數學","複變函式與積分變換","關係代數"],
course:[]
}
}
render(){
return (
<React.Fragment>
<label>選修:</label>
<select value={this.state.course} onChange={(event)=>this.courseChange(event)} multiple size={this.state.courses.length}>
{
this.state.courses.map((item,index)=>{
return <option key={index} value={item}> {item} </option>
})
}
</select>
<div><button onClick={()=>this.getCourse()}>所選選修課</button></div>
</React.Fragment>
)
}
}
在上述程式碼中,state區定義了兩個資料:courses作為陣列提供所有備選的選修課程內容,course用來儲存使用者選擇的選修課程內容,因為是多選,因此資料型別為陣列。
這裡提供兩種不同的機制來完成<select>標記的onChange事件。
1、不借助鍵盤快捷鍵實現多選。
courseChange(event){
let value=event.target.value;
let course=[...this.state.course];
// 判斷value值是否在course陣列中出現過
let index=course.findIndex(item=>item===value);
if(index>=0){
course.splice(index,1);
}else{
course.push(value);
}
this.setState({course});
}
2、藉助鍵盤快捷鍵實現多選。
courseChange(event){
let options=event.target.options;
let temp=[]; //盛放被選中的option項的索引值的陣列
for(let i in options){
if(options[i].selected){
temp.push(i);
}
}
let course=temp.map(item=>options[item].value);
this.setState({course});
}
上述原理形成的程式碼可以簡化為以下ES6程式碼:
let options=event.target.options;
let course=Object.keys(options).filter(item=>options[item].selected===true).map(item=>options[item].value);
this.setState({course});
總結
本文是React系列教程的第六篇文章,主要為大家講解了React表單元素的受控元件操作。文字框、密碼域、多行文字域、select列表、select選單都是採用value-onChange組合來實現受控操作的。單選框、複選框是採用checked-onChange組合來實現受控操作的。同時具有複選功能的複選框和列表需要藉助陣列來接收使用者所選的內容,操作起來較為複雜。明天會為大家系統的講解React中非受控表單元素的使用方法。
關於作者
小海前端,具有18年Web專案開發和前後臺培訓經驗,在前端領域著有較為系統的培訓教材,對Vue.js、微信小程式開發、uniApp、React等全棧開發領域都有較為深的造詣。入住CSDN,希望能夠更多的結識Web開發領域的同仁,將Web開發大力的進行普及。同時也願意與大家進行深入的技術研討和商業合作。