我們知道,在 react 中,事件處理函數(shù)中的this很容易丟失,如:
class App extends React.Component {
handleClick() {
console.log(this);// undefined
}
render() {
return <div onClick={this.handleClick} >點(diǎn)我</div>;
}
}
有4種this指向的解決方案 , 如下:
- 箭頭函數(shù)
- 構(gòu)造函數(shù)中的 bind
- 事件綁定時(shí)的 bind
- 事件綁定時(shí)的匿名函數(shù)+箭頭函數(shù)。
下邊我們分別給出它們的實(shí)現(xiàn)
箭頭函數(shù)
class App extends React.Component {
// 修改為箭頭函數(shù)
handleClick = () => {
console.log(this);// 正常
}
render() {
return <div onClick={this.handleClick} >點(diǎn)擊</div>;
}
}
構(gòu)造函數(shù)中的bind
class App extends React.Component {
constructor(props) {
super();
// 通過bind 改寫this指向并返回新的函數(shù)
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
console.log(this);// 正常
}
render() {
// bind
return <div onClick={this.handleClick} >點(diǎn)擊</div>;
}
}
事件綁定時(shí)的bind
class App extends React.Component {
handleClick() {
console.log(this);// 正常
}
render() {
// bind
return <div onClick={this.handleClick.bind(this)} >點(diǎn)擊</div>;
}
}
如需傳遞參數(shù),如下:
class App extends React.Component {
handleClick(a, b, e) {
console.log(this);// 正常
console.log(a, b, e);// "aa","bb","事件對(duì)象"
}
render() {
return <>
<div onClick={this.handleClick.bind(this, "aa", "bb")} >點(diǎn)擊</div>
</>
}
}
事件綁定時(shí)的匿名函數(shù)+箭頭函數(shù)
class App extends React.Component {
handleClick(e) {
console.log(this);// 正常
}
render() {
// bind
return <div onClick={() => this.handleClick()} >點(diǎn)擊</div>;
}
}
如需傳遞參數(shù),如下:
class App extends React.Component {
handleClick(a, b, e) {
console.log(this);// 正常
console.log(a, b, e);// "aa","bb","事件對(duì)象"
}
render() {
// bind
return <div onClick={(e) => this.handleClick('aa', 'bb', e)} >點(diǎn)擊</div>;
}
}
另外, 也可自定義屬性,如下:
class App extends React.Component {
handleClick(e) {
console.log(this);// 正常
console.log(e.target.dataset.msg);// "aa"
}
render() {
return <>
<div data-msg="aa" onClick={this.handleClick.bind(this)} >點(diǎn)擊</div>
</>
}
}
但是,如果從性能角度出發(fā),只推薦一種: 事件綁定時(shí)的bind
this指向解決方案的性能比較
以下比較,主要從 實(shí)例成員函數(shù)能否得到復(fù)用觸發(fā),那么我們可以將其函數(shù)成員做對(duì)比,看哪種方式是共享內(nèi)存。
class App extends React.Component {
constructor() {
super();
this.ref1 = React.createRef();
this.ref2 = React.createRef();
}
handleClick(e) {
console.log(this.ref1.current.showBtn === this.ref2.current.showBtn);
}
render() {
return <>
<div onClick={this.handleClick.bind(this)} >
<Btn ref={this.ref1} />
<Btn ref={this.ref2} />
</div>
</>
}
}
1. 箭頭函數(shù)
class Btn extends React.Component {
showBtn = () => {
console.log(this);
}
render() {
return <button onClick={this.showBtn}>點(diǎn)擊</button>;
}
}
結(jié)果如下:
handleClick(e) {
console.log(this.ref1.current.showBtn === this.ref2.current.showBtn);// false
}
說明:箭頭函數(shù)不靠譜
2. 構(gòu)造函數(shù)中的 bind
class Btn extends React.Component {
constructor() {
super();
this.showBtn = this.showBtn.bind(this);
}
showBtn() {
console.log(this);
}
render() {
return <button onClick={this.showBtn}>點(diǎn)擊</button>;
}
}
結(jié)果如下:
handleClick(e) {
console.log(this.ref1.current.showBtn === this.ref2.current.showBtn); // false
}
說明:構(gòu)造函數(shù)中的 bind不靠譜
3. 事件綁定時(shí)的 bind
class Btn extends React.Component {
showBtn() {
console.log(this);
}
render() {
return <button onClick={this.showBtn.bind(this)}>點(diǎn)擊</button>;
}
}
結(jié)果如下:
handleClick(e) {
console.log(this.ref1.current.showBtn === this.ref2.current.showBtn); // true
}
說明:事件綁定時(shí)的 bind 靠譜!
**4. 事件綁定時(shí)的匿名函數(shù)+箭頭函數(shù) **
class Btn extends React.Component {
showBtn() {
console.log(this);
}
render() {
return <button onClick={() => this.showBtn()}>點(diǎn)擊</button>;
}
}
結(jié)果如下:
handleClick(e) {
console.log(this.ref1.current.showBtn === this.ref2.current.showBtn); // true
}
說明: 事件綁定時(shí)的匿名函數(shù)+箭頭函數(shù) 靠譜!
結(jié)論, 就推薦以下2種寫法就行了:
1. 事件綁定時(shí)的 bind
class Btn extends React.Component {
showBtn() {
console.log(this);
}
render() {
return <button onClick={this.showBtn.bind(this)}>點(diǎn)擊</button>;
}
}
2. 事件綁定時(shí)的匿名函數(shù)+箭頭函數(shù)
class Btn extends React.Component {
showBtn() {
console.log(this);
}
render() {
return <button onClick={() => this.showBtn()}>點(diǎn)擊</button>;
}
}