一、React事件命名
不同於Vue,React的事件處理機制更加接近於原生事件的寫法、
對於事件類型的指定,基本上是採用原生的寫法(但是具體事件回調函數的指定有所不同):
<button onClick={activateLasers}> Activate Lasers
</button>
即使用on+大寫事件類型的形式
二、React事件參數:event對象
React中會默認傳入event對象,這個event對象遵循W3C規範(也就是原生類似)
三、React阻止html元素的默認行爲
在原生JavaScript中,如果要阻止元素的默認行爲(比如說點擊a標籤默認打開鏈接),是在回調函數的最後return false
但是在React,無法使用此方法,必須調用event對象中的preventDefault
方法
比如:
function ActionLink() {
// 使用閉包指定對應回調函數
function handleClick(e) {
e.preventDefault();
console.log('The link was clicked.');
}
return (
<a href="#" onClick={handleClick}> Click me
</a>
);
}
四、在class組件和function組件中指定處理函數的通常格式
- 在class組件中,我們通常將回調函數作爲class對象的成員函數:
比如官方文檔中這段代碼:
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')
);
需要注意的有如下幾點:
-
所有的handleClick,在外面使用的時候都必須是以this.handleClick的形式進行調用,表示調用的handleClick是當前class的成員函數.
-
由於JavaScript的回調函數機制,class定義的回調方法,在回調的時候,是不綁定this的(也就是說,回調的時候的this,是undefinded),關於這點,我們可以試試添加以下打印函數進行嘗試:
class Link extends React.Component { constructor(props) { super(props); // 不給回調函數綁定this // this.handleClick = this.handleClick.bind(this); } handleClick(event) { //回調時候返回值應該是undefinded console.log("不綁定this,進行回調函數的時候:") console.log(this); // console.log(event); event.preventDefault(); alert("clicked a "); }; render() { // 非回調的時候 console.log("非回調,在類中:") console.log(this); return ( <div> <a href="xgpax.top" onClick={this.handleClick}>aaaa</a> </div> ); } } ReactDOM.render(<Link />, document.getElementById("app"));
顯示結果:
很明顯,我們可以看到回調函數中的this指向爲undefined,所以我們需要給回調函數指定this,而這個指定方法,就是function.bind()方法(指定bind這種方法,其實不推薦使用,下文的推薦也只是一種相對而言)。
有兩種指定方法:
1. 在調用時指定(不推薦)
<a href="xgpax.top" onClick={this.handleClick.bind(this)}>aaaa</a>
- 在constructor時指定(推薦)
constructor(props) {
super(props);
// 給回調函數綁定this
this.handleClick = this.handleClick.bind(this);
}
而現代化的寫法,我們在第五點中講(由於react hooks,class組件也不是很常用了)
- 函數式組件的事件綁定機制:
// 函數式事件處理
function Link() {
let test = 1;
function handleClick(event) {
console.log(event);
// 嘗試打印test 證明可以使用閉包外的變量
console.log(test); // 1 打印成功
// 用來阻止默認事件的觸發
event.preventDefault();
alert("clicked a!")
};
return (
<div>
<a href="xgpax.top" onClick={handleClick}>aaaa</a>
</div>
);
}
在這裏需要看到的是,函數內部沒有this指針,所以沒有上述困擾(由於react hooks,函數式逐漸已經成爲主流)
我們採用閉包的方法來定義回調函數,由於閉包的變量機制,也就不會出現變量指向問題。
五、class組件使用ES6的箭頭函數來綁定事件:
使用 bind
很麻煩,我們可以利用箭頭函數與上層共享this的方法來解決,這裏有兩種方式可以解決:
-
在定義事件的回調函數的時候,使用箭頭函數,然後在箭頭函數內部定義要執行的方法(可以指定自己需要指定的參數)
class LoggingButton extends React.Component { handleClick() { console.log('this is:', this); } render() { // 此語法確保 `handleClick` 內的 `this` 已被綁定。 return ( <button onClick={() => this.handleClick()}> Click me </button> ); } }
-
將回調函數修改爲箭頭函數的形式,用
變量名=()=>{}
的形式進行定義(create-react-app默認使用這種形式,主流)。
class LoggingButton extends React.Component { // 此語法確保 `handleClick` 內的 `this` 已被綁定。 handleClick = () => { console.log('this is:', this); } render() { return ( <button onClick={this.handleClick}> Click me </button> ); } }
六、react回調函數事件的傳參
顯然,默認的event事件無法解決所需要的所有情景,而使用類似小程序中data-set的形式又不夠現代,且繁瑣。
我們有如下指定方式:
-
還是利用es6箭頭函數語法
<button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button>
-
利用bind進行傳參
<button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>
在這兩種情況下,React 的事件對象
e
會被作爲第二個參數傳遞。如果通過箭頭函數的方式,事件對象必須顯式的進行傳遞,而通過bind
的方式,事件對象以及更多的參數將會被隱式的進行傳遞。