react表單和綁定事件及state和props-04

一、綁定事件

1、綁定事件處理函數this獲取數據的幾種方法:

第一種方式:在事件上使用bind(this)

<button onClick={this.getData1.bind(this)}>獲取數據方法1</button>

第二種方式:在構造函數中改變this指向

this.getData2=this.getData2.bind(this)
<button onClick={this.getData2}>獲取數據方法2</button>

第三種方式:使用=()=>

getData3=()=>{
    alert(this.state.dataMsg)
}
<button onClick={this.getData3}>獲取數據方法3</button>

關于React中this指向問題

JavaScript函數中的this不是在函數聲明的時候定義的,而是在函數調用(即運行)的時候定義的。在react中也遵循這個原則,this指向該function的調用方,所以“調用者”不同會導致this的不同,這里的“調用者”指的是函數執行時的當前對象。

箭頭函數或是bind會改變this的指向。上面的this.state,之所以能夠訪問到state就是改變了this的指向,不然getData里的this就是指向這個function,這是的this是undefined。

一般來說:
????1、誰調用的this就指向誰。
????2、箭頭函數,bind改變后的指向父層。

2、對state中的數據進行賦值

在react中我們使用setState來更新數據:

dataMsg:'原數據'
setData=()=>{
    //此處使用setState來更新數據
    this.setState({
        dataMsg:'數據已被改變'
    })
    console.log(this.state.dataMsg)
}

但是console打印出來的值是:原數據。
這里就要提到react里setState的異步了,在react里setState這個方法是異步的,不會按順序執行,它可能會等待一組state一起進行更新,來提高性能。下面提供一個解決辦法,setState的回調setState(updater[, callback]),相當于componentDidUpdate函數:

setData=()=>{
    //此處使用setState來更新數據
    //setState的回調setState(update, ()=>{//更新完后執行的代碼}),
    this.setState({
        dataMsg:'數據已被改變'
    },()=>{
        console.log(this.state.dataMsg)
    }
}
3、方法的傳值

因為在事件中使用onClick={this.setData()}時方法直接執行,直接寫成this.setData(data)這樣會報錯,所以需要使用bind():

//看參數,第一個參數需要是this或是一個函數
//第二個參數為需要傳遞參數
bind(this: Function, thisArg: any, ...argArray: any[]): any)

下面看如何傳遞:

<button className="myFormEvent-setData2-btn" onClick={this.setData.bind(this,["第一個參數","第二個參數","第三個參數"])}>執行方法傳值2</button>
//多個參數時str即為數組
setData=(str)=>{
  this.state({
    msg:str[0],
    dataMsg:str[2]
  })
}

二、事件對象

事件對象:在出發DOM上的某個事件時,會產生一個事件對象event,這個對象中包含著所有與事件有關的信息。

1、使用event.target獲取相關屬性值:
event.target.style.background //獲取或更改背景色
event.target.getAttribute("aid") //獲取自定義屬性的值
event.target.setAttribute("aid","aaa")//設置自定義屬性的值
e.target.value //獲取輸入框的值
//按鈕點擊事件
<button aid="aaa" onClick={this.getEvent}></button>
getEvent=(event)=>{
    //使用event.target來改變顏色
    event.target.style.background="red";
    //使用event.target.getAttribute("aid")里獲取button的自定義屬性aid的值
    //使用event.target.setAttribute("aid","aaa")來設置button的自定義屬性aid的值
    console.log(event.target.getAttribute("aid"));
}
//輸入框改變事件
<input onChange={this.inputChange}></input>
inputChange=(e)=>{
    //使用event.target.value獲取表單輸入值
    console.log(e.target.value);
}
2、使用this.refs來獲取值

給標簽添加ref屬性,在事件里通過this.refs.[屬性].value來獲取值

<input ref="val" onChange={this.refChange}/><button onClick={this.getRefVal}>通過ref獲取輸入框的值</button>
refChange=()=>{
    //獲取值
    let str = this.refs.val.value;
    this.setState({
        val:str
    })
}
3、event的部分事件
輸入框事件:
  onChange:輸入框改變時觸發
鍵盤事件:
  onKeyUp:按鍵抬起時觸發
  onKeyDown:按鍵按下時觸發
點擊事件:
  onClick:點擊時觸發

三、react的表單

1、雙向數據綁定

雙向數據綁定在vue中有,在react中是沒有的,雙向數據綁定就是雙方的數據改變相互影響,下面只是模擬雙向數據綁定:

//輸入框使用value時需要添加onChange監聽事件
//還可以使用defaultValue
<input value={this.state.data} onChange={this.inputDataChange} /><button onClick={this.getInputData}>改變model數據為data</button><br/>
數據顯示:{this.state.data}<br/>

//初始化
constructor(props){
    super(props);
    this.state={
        data:'data'
    }
}
//輸入框值改變時改變state的值,視圖上相對改變
inputDataChange=(e)=>{
    //此處是輸入框狀態改變的數據
    this.setState({
        data:e.target.value
    })
}
//相當于state的值改變,視圖上的值也改變
getInputData=()=>{
    //此處是點擊時要改變的數據
    this.setState({
        data:'data'
    })
}

上面的的value需要事件監聽,這里面有一個react的知識點:約束性組件和非約束性組件
約束性組件,簡單說就是react管理了它的value,而非約束性組件的value是由原生DOM管理的。

約束性組件是這樣寫的:

<input value={this.state.data} onChange={this.inputDataChange} />

這里的value屬性不再是一個寫死的值,它是this.state.data,而this.state.data是由this.inputDataChange這個監聽事件負責管理的。
這個時候實際上 input 的 value 根本不是用戶輸入的內容。而是onChange 事件觸發之后,由 this.setState 導致了一次重新渲染。不過React會優化這個渲染過程,實際它依然是通過設置input的value來實現的。

非約束性組件是這樣寫的:

<input defaultValue="a" />

這個defaultValue就是原生DOM中的value屬性,其value值就是用戶輸入的內容,react不管理輸入的過程。

對比約束性組件和非約束性組件的輸入流程:
*約束性組件: 用戶輸入A -> 觸發onChange事件 -> inputDataChange 中設置 state.name = “A” -> 渲染input使他的value變成A
*非約束性組件: 用戶輸入A -> input 中顯示A

2、react表單的寫法

這里介紹form表單里的幾種常用的子標簽:
一般表單都是需要用form標簽包起來:

<form></form>
  • 阻止表單的默認提交
    有時我們需要阻止表單的默認提交,來自己把握什么時候提交調用preventDefault()方法,如下:
<form onSubmit={this.doSubmit}></form>
doSubmit=(e)=>{
    //使用事件e來調 preventDefault()方法來阻止表單默認提交
    e.preventDefault();
}
  • 文本框
    設置value屬性,因為是約束性組件,所以需要onChange觸發事件,下面的都是這樣
    在事件方法handleName(event)里使用event.target.value來獲取輸入框中的值,如下:
constructou(props){
    super(props);
    this.state={
        name:''
    }
}
handleName=(e)=>{
    this.setState({
        name:e.target.value
    })
}

姓名:<input type="text" value={this.state.name} onChange={this.handleName}  />
  • 單選框
    單選框非手動輸入,所以需要在標簽上加入value屬性,否則獲取不到數據。因為我們要選擇,所以要添加checked,來判斷選中狀態:
constructou(props){
    super(props);
    this.state={
       //默認選中女
        sex:'0'
    }
}
/**
    checked={this.state.sex==0}是判斷是否為選中狀態
    當點擊選中按鈕后獲取當前選中的value值,然后改變sex的值
    react重新渲染后,點擊的按鈕變為被選中狀態
*/
handleSex=(e)=>{
    this.setState({
        sex:e.target.value
    })
}

性別:<input type="radio" checked={this.state.sex==0} value="0" onChange={this.handleSex} />男
      <input type="radio" checked={this.state.sex==1} value="1" onChange={this.handleSex} />女
  • 下拉框
    下拉框里的數據是數組,所以我們需要用到循環獲取,我們需要有個變量city來存儲選中的值,看代碼:
constructou(props){
    super(props);
    this.state={
        city:'',
        citys:[
             '北京','上海','深圳'
        ]
    }
}
handleCity=(e)=>{
    this.setState({
        city:e.target.value
    })
}

/**
    使用map()來循環數據,注意map(function(value,key){})
    的this的指向,此時的this是無法調用state的
    注意:return中是需要一個根標簽包裹的,此處<option>即可
    需要在option上添加key,map循環需要,以便更好的管理數據
*/
城市:
<select value={this.state.city} onChange={this.handleCity}>
    {this.state.citys.map(function(value,key){
        return(
            <option key={key} >{value}</option>
        )
    })}
</select>
  • 復選框
constructou(props){
    super(props);
    this.state={
        hobby:[
            {'title':'睡覺','checked':true},
            {'title':'吃飯','checked':false},
            {'title':'聽音樂','checked':false}
        ]
    }
}
/**
    hobby是個數組,我們通過key來找到選中狀態,當點擊時通過
    hobby[key].checked = !hobby[key].checked;
    來改變選中狀態,然后將hobby重新賦值,和單選框類似
*/
handleHobby(key){
    var hobby = this.state.hobby;
    hobby[key].checked = !hobby[key].checked;
    this.setState({
        hobby:hobby
    })
}

/**
    因為我們需要key來找到選項的選中狀態,所以我們需要把key傳到方法中,
    此處使用箭頭函數將map函數中的this指向調整了,所以在return中可以是用this.handleHobby
*/
喜好:
{this.state.hobby.map((value,key)=>{
    return(
        <span key={key}>
            <input type="checkbox" checked={value.checked} onChange={this.handleHobby.bind(this,key)}/>{value.title}
        </span>
    )
})}
  • 文本域
    和文本框類似:
constructou(props){
    super(props);
    this.state={
        info:''
    }
}
handleInfo=(e)=>{
    this.setState({
        info:e.target.value
    })
}

info:<input  type="textarea" value={this.state.info} onChange={this.handleInfo}/>

四、react中的state和props

props

1、react的組件從概念上看就是一個函數,可以接受一個參數最為輸入值,這個參數就是props,可以把props理解為從外部傳入組件內部的數據。
2、props經常被用作渲染組件和初始化狀態,當一個組件被實例化之后,它的props是只讀的,不可改變的。如果props在渲染過程中可以被改變,會導致這個組件顯示的形態變得不可預測。只有通過父組件重新渲染的方式才可以把新的props傳入組件中。
3、在組件中,我們最好為props中的參數設置一個defaultProps,并且制定它的類型。

state

一個組件的顯示形態可以由數據狀態和外部參數所決定,外部參數也就是props,而數據狀態就是state
state的主要作用是用于組件保存、控制以及修改自己的狀態,它只能在constructor中初始化,它算是組件的私有屬性,不可通過外部訪問和修改,只能通過組件內部的this.setState來修改,修改state屬性會導致組件的重新渲染。


寫在最后:

  • 如果文章中有錯誤或是表達不準確的地方,歡迎大家評論中指正,以便我完善。
  • 文章我也會根據所學到新的知識不斷更新。
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。