React進(jìn)階-事件處理

React元素的事件處理和 DOM元素的很相似。但是有一點(diǎn)語(yǔ)法上的不同:

!React事件綁定屬性的命名采用駝峰式寫法,而不是小寫

!如果采用 JSX的語(yǔ)法,你需要傳入一個(gè)函數(shù)作為事件處理函數(shù),而不是一個(gè)字符串(DOM元素的寫法)

// 傳統(tǒng)的HTML

<button onclick="clickFun()">
? ? 點(diǎn)擊按鈕
</button>

// React 語(yǔ)法

<button onClick={clickFun}>
? ? 點(diǎn)擊按鈕
</button>

!在 React中另一個(gè)不同的是,你不能使用返回 false的方式阻止默認(rèn)行為。你必須明確的使用preventDefault。

// 傳統(tǒng)的 HTML中阻止鏈接默認(rèn)打開一個(gè)新頁(yè)面

<a href="#" onclick="console.log('這個(gè)鏈接被點(diǎn)擊了。'); return false">
? ? 點(diǎn)我
</a>

// React 語(yǔ)法

function ActionLink () {
? ? function handleClick (e) {
? ? ? ? e.preventDefault();
? ? ? ? console.log('The link was clicked.');
? ? }

? ? return (
? ? ? ? <a href="#" onClick={handleClick}>
????????????點(diǎn)我
????????</a>
????);
}

使用 React的時(shí)候通常不需要你使用 addEventListener 為一個(gè)已創(chuàng)建的 DOM元素添加監(jiān)聽器。你僅僅需要在這個(gè)元素初始渲染的時(shí)候提供一個(gè)監(jiān)聽器。

當(dāng)你使用 ES6 class 語(yǔ)法來定義一個(gè)組件的時(shí)候,事件處理器會(huì)成為類的一個(gè)方法。例如,下面的 Toggle組件渲染一個(gè)讓用戶切換開關(guān)狀態(tài)的按鈕:

class Toggle extends React.Component {

? ? constructor (props) {
? ? ? ? super (props);
? ? ? ? this.state = {isToggleOn: true};
? ? ? ? this.handleClick = this.handleClick.bind(this);
????}

? ? handleClick () {
? ? ? ? this.setState (prevState => ({
? ? ? ? ? ? isToggleOn: !prevState.isToggleOn
? ? ? ? }));
????}

? ? render () {
? ? ? ? return (
? ? ? ? ? ? <button onClick={this.handleClick}>
? ? ? ? ? ? ? ? {this.state.isToggleOn ? 'ON' : 'OFF'}
? ? ? ? ? ? </button>
????????);
????}
}

ReactDOM.render(
? ? <Toggle />,
? ? document.getElementById('root')
);

你必須謹(jǐn)慎對(duì)待 JSX 回調(diào)函數(shù)中的 this,類的方法默認(rèn)是不會(huì)綁定 this的。如果你忘記綁定this.handleClick 并把它傳入 onClick,當(dāng)你調(diào)用這個(gè)函數(shù)的時(shí)候 this的值會(huì)是 undefined。

這并不是 React的特殊行為;它是函數(shù)如何在 JavaScript中運(yùn)行的一部分。通常情況下,如果你沒有在方法后面添加 (),例如 onClick = {this.handleClick}, 你應(yīng)該為這個(gè)方法綁定 this。

如果使用 bind 讓你很煩,這里有兩種方式可以解決。如果你正在使用實(shí)驗(yàn)性的屬性初始化語(yǔ)法,你可以使用屬性初始化器來正確的綁定回調(diào)函數(shù):

// 這個(gè)語(yǔ)法在 Create React App 中默認(rèn)開啟。

class LoggingButton extends React.Component {

? ? handleClick = () => {
? ? ? ? console.log('this is:', this);
????}

? ? render () {
? ? ? ? <button onClick={this.handleClick}>
? ? ? ? ? ? 點(diǎn)我
????????</button>
????}

}

如果你沒有使用屬性初始化器語(yǔ)法,你可以在回調(diào)函數(shù)中使用 箭頭函數(shù):

class LoggingButton extends React.Component {
? ? handleClick () {
? ? ? ? console.log('this is:', this);
????}??

? ? render () {
? ? ? ? return (
? ? ? ? ? ? <button onClick={ (e) => this.handleClick(e) }>
? ? ? ? ? ? ? ? 點(diǎn)我? ??
????????????</button>
????????);
????}

}

使用這個(gè)語(yǔ)法有個(gè)問題就是每次 LoggingButton 渲染的時(shí)候都會(huì)創(chuàng)建一個(gè)不同的回調(diào)函數(shù)。在大多數(shù)情況下,這沒有問題。然而如果這個(gè)回調(diào)函數(shù)作為一個(gè)屬性值傳入低階組件,這些組件可能會(huì)進(jìn)行額外的重新渲染。

我們通常建議在 構(gòu)造函數(shù)匯中綁定 或 使用屬性初始化器語(yǔ)法 來避免這類性能問題。

向事件處理程序傳遞參數(shù)

通常我們會(huì)為事件處理程序傳遞額外的參數(shù)。

例如,若是 id是你要?jiǎng)h除那一行的id,以下兩種方式都可以向事件處理函數(shù)傳遞參數(shù):

<button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button>
<button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>

上述兩種方式是等價(jià)的,分別通過 arrow functions 和 Function.prototype.bind 來為事件處理函數(shù)傳遞參數(shù)。

上面兩個(gè)例子中,參數(shù) e作為 React事件對(duì)象將會(huì)被作為第二個(gè)參數(shù)進(jìn)行傳遞。通過箭頭函數(shù)的方式,事件對(duì)象必須顯式的進(jìn)行傳遞,但是通過 bind的方式,事件對(duì)象以及更多的參數(shù)將會(huì)被隱式的進(jìn)行傳遞。

值得注意的是,通過 bind方式向監(jiān)聽函數(shù)傳參,在類組件中定義的監(jiān)聽函數(shù),事件對(duì)象 e要排在所傳遞參數(shù)的后面,例如:

class Popper extends React.Component {

? ? constructor () {
? ? ? ? super ();
? ? ? ? this.state = {name: 'Hello world!'};
????}

? ? preventPop (name, e){? ?//事件對(duì)象 e要放在最后
? ? ? ? e.preventDefault();
? ? ? ? alert(name);
????}

? ? render (){
? ? ? ? return (
? ? ? ? ? ? <div>
? ? ? ? ? ? ? ? <p>hello</p>
? ? ? ? ? ? ? ? <a ? onClick={this.preventPop.bind(this,this.state.name)}></a>
????????????</div>
????????)
????}

}


參考網(wǎng)址:

事件處理—React

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容