原文連接:reactjs.org/docs/handli…html
處理React元素的事件與處理DOM元素上的事件十分類似,它們僅有一些語法上的區別。react
例如,在HTML上瀏覽器
<button onclick="activateLasers()">
Activate Lasers
</button>
複製代碼
在React中則略微不一樣bash
<button onClick={activateLasers}>
Activate Lasers
</button>
複製代碼
React上的另外一個不一樣之處在於你不能返回false
去阻止默認行爲,必須顯示地調用preventDefault
才能阻止默認行爲。函數
在HTML中,爲了阻止錨點連接默認打開一個新頁面能夠這樣寫:性能
<a href="#" onclick="console.log('The link was clicked.'); return false">
Click me
</a>
複製代碼
可是在React中,須要這樣寫才能阻止打開新頁面:ui
function ActionLink() {
function handleClick(e) {
e.preventDefault();
console.log('The link was clicked.');
}
return (
<a href="#" onClick={handleClick}>
Click me
</a>
);
}
複製代碼
在這裏,e
是一個合成事件。React根據W3C規範
來定義這些合成事件,因此無需擔憂瀏覽器的兼容問題。this
使用React時,一般不須要調用addEventListener
來爲已建立的DOM元素添加監聽器。取而代之的是在元素被渲染之初提供一個監聽器。spa
當你定義了一個ES6 class組件時,一個經常使用的方法是將事件處理器聲明爲class的一個方法。下面的代碼聲明瞭一個Toggle
組件,讓用戶能在ON和OFF兩種狀態之間切換。prototype
class Toggle extends React.Component {
constructor(props) {
super(props);
this.state = {isToggleOn: true};
// 這段代碼讓this在回調函數中可以有效
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState(state => ({
isToggleOn: !state.isToggleOn
}));
}
render() {
return (
<button onClick={this.handleClick}>
{this.state.isToggleOn ? 'ON' : 'OFF'}
</button>
);
}
}
ReactDOM.render(
<Toggle />,
document.getElementById('root')
);
複製代碼
必須謹慎對待JSX回調函數中的this
,在Javascript中,class方法是不會默認綁定this
的。若是你忘記綁定this.handleClick
並將它傳遞給onClick
,那麼當這個方法被調用時瀏覽器將沒法識別this
,由於此時this
是undefined
。
這不是React特有的特性,這與JavaScript的工做原理相關。一般來講,若是不在方法後面加上()
,好比onClick={this.handleClick}
,咱們就應該綁定它。
若是以爲綁定方法很麻煩,這裏有兩種選擇能夠避免綁定。若是你正在使用實驗性的public class fields語法
,你可使用class fields
正確綁定回調。
class LoggingButton extends React.Component {
// 這個語法能夠確保回調函數已經綁定了this
// 但請注意這是實驗性的語法
handleClick = () => {
console.log('this is:', this);
}
render() {
return (
<button onClick={this.handleClick}>
Click me
</button>
);
}
}
複製代碼
這種語法在使用Create React App建立的項目中是可使用的。
若是沒有使用class fields語法
,那麼你能夠在回調函數中使用箭頭函數。
class LoggingButton extends React.Component {
handleClick() {
console.log('this is:', this);
}
render() {
// 這段代碼確保了handleClick綁定了this
return (
<button onClick={(e) => this.handleClick(e)}>
Click me
</button>
);
}
}
複製代碼
可是這個語法有一個問題,每當LoggingButton被渲染時都會建立一個不一樣回調函數。在大多數狀況下這是沒有問題的,可是若是這個回調函數做爲props傳遞給子組件時,這些組件可能會作一個額外的從新渲染。因此咱們一般推薦在構造函數中綁定事件或者使用class fields語法來綁定以免此類的性能問題。
在循環中咱們一般須要傳遞一個額外的參數給事件處理函數。好比若是id時想要刪除的那一行的id,如下兩種方法均可以將id傳遞給事件處理函數。
<button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button>
<button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>
複製代碼
上面兩行代碼是等價的,只不過度別使用了箭頭函數
和Function.prototype.bind
。
在上面的兩個例子中,合成事件e表明了React事件,都做爲第二個參數傳遞給事件處理函數。在箭頭函數中咱們須要顯示地傳遞e,可是使用bind方法,事件對象以及更多的參數都被隱式地傳遞。