使用React元素處理事件和在DOM元素上處理事件非常相似。
有一些語(yǔ)法差異:
- React事件使用駝峰式命名,而非小寫。
- 在JSX中,你傳入一個(gè)函數(shù)作為時(shí)間處理器,而非一個(gè)字符串。
舉個(gè)例子,下面這個(gè)HTML:
<button onclick="activateLasers()">
Activate Lasers
</button>
在React中有些許不同:
<button onClick={activateLasers}>
Activate Lasers
</button>
另外一處不同就是在React中你不能返回false來阻止默認(rèn)行為。你必須顯式地調(diào)用preventDefault。舉例來說,在簡(jiǎn)單的HTML中,如果你想阻止鏈接打開一個(gè)新頁(yè)面的這個(gè)默認(rèn)行為,可以這么寫:
<a href="#" onclick="console.log('The link was clicked.'); return false">
Click me
</a>
在React中,是這樣的:
function ActionLink() {
function handleClick(e) {
e.preventDefault();
console.log('The link was clicked.');
}
return (
<a href="#" onClick={handleClick}>
Click me
</a>
);
}
這里,e是一個(gè)合成的事件。React依照W3C規(guī)則定義的這些合成事件,因此你無需擔(dān)心瀏覽器之間的兼容性。查看SyntheticEvent參考指南來了解更多。
在使用React時(shí),一般來說你不需要在一個(gè)DOM元素創(chuàng)建后調(diào)用addEventListener來為其添加監(jiān)聽器。而應(yīng)該在元素初始化渲染的時(shí)候提供一個(gè)監(jiān)聽器。
當(dāng)你使用ES6類去定義一個(gè)組件時(shí),一個(gè)事件處理器一般作為類的方法而存在。舉例來說,下面這個(gè)Toggle組件渲染一個(gè)可以讓用戶在"ON"和"OFF"狀態(tài)間切換的按鈕:
class Toggle extends React.Component {
constructor(props) {
super(props);
this.state = {isToggleOn: true};
// This binding is necessary to make `this` work in the callback
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')
);
在CodePen上試一試
在JSX的回調(diào)函數(shù)中你必須格外小心this的含義。在JavaScript中,類方法默認(rèn)不會(huì)被綁定。如果你忘記綁定this.handleClick,然后將他傳遞給onClick,當(dāng)這個(gè)函數(shù)被調(diào)用時(shí),this將會(huì)是undefined。
這不只是React才有的行為;這是由于JavaScript中函數(shù)工作的方式導(dǎo)致的。通常情況下,如果你引用一個(gè)方法,但是后面沒有加上(),比如onClick={this.handleClick},那你就應(yīng)該綁定那個(gè)方法。
如果調(diào)用bind讓你很煩惱,這有兩個(gè)方法可以讓你解決這個(gè)問題。如果你正在使用還在試驗(yàn)階段的屬性初始化語(yǔ)法,那你就可以使用屬性初始化來正確的綁定回調(diào):
class LoggingButton extends React.Component {
// This syntax ensures `this` is bound within handleClick.
// Warning: this is *experimental* syntax.
handleClick = () => {
console.log('this is:', this);
}
render() {
return (
<button onClick={this.handleClick}>
Click me
</button>
);
}
}
在創(chuàng)建React應(yīng)用中,這個(gè)語(yǔ)法是默認(rèn)開啟的。
如果你沒有在使用屬性初始值語(yǔ)法,也可以在回調(diào)函數(shù)中使用箭頭函數(shù):
class LoggingButton extends React.Component {
handleClick() {
console.log('this is:', this);
}
render() {
// This syntax ensures `this` is bound within handleClick
return (
<button onClick={(e) => this.handleClick(e)}>
Click me
</button>
);
}
}
這種語(yǔ)法的問題就是每次LogginButton渲染的時(shí)候,都會(huì)創(chuàng)建一個(gè)不同的回調(diào)函數(shù)。多數(shù)情況下這都是可以接受的。但如果這個(gè)回調(diào)作為prop傳遞給下面的組件,下面的這些組件可能會(huì)進(jìn)行額外的重新渲染。我們通常建議在構(gòu)造函數(shù)中綁定或使用屬性初始器語(yǔ)法來避免這種性能問題。