React事件處理函數(shù)綁定this的集中方法
目前React有三種方法可以創(chuàng)建組件,其中使用React.createClass()函數(shù)創(chuàng)建的組件,this會自動
綁定到組件的每個(gè)方法中;而使用Class Component或者Functional Component時(shí),需要手動綁定this.
1. 在構(gòu)造函數(shù)中綁定
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')
);
2.使用class properties進(jìn)行綁定
class properties目前處于state-2草案階段,babel已經(jīng)支持
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>
);
}
}
3. 使用箭頭函數(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>
);
}
}
這種方式有一個(gè)潛在的性能問題,就是每次組件渲染時(shí),onClick的回調(diào)函數(shù)都是不同的匿名函數(shù),如果這個(gè)組件把回調(diào)函數(shù)通過props傳遞到其子組件,那么由于每次組件的渲染時(shí),由于傳遞的props中回調(diào)函數(shù)的變化,就會導(dǎo)致子組件的額外渲染(是不同的回調(diào)函數(shù),但實(shí)際上處理邏輯完全相同)。
4. 使用bind()
class LoggingButton extends React.Component {
handleClick() {
console.log('this is:', this);
}
render() {
// This syntax ensures `this` is bound within handleClick
return (
<button onClick={this.handleClick.bind(this)}>
Click me
</button>
);
}
}
bind跟使用箭頭函數(shù)一樣,實(shí)際上每次組件渲染時(shí)都生成了新的回調(diào)函數(shù)。
建議使用構(gòu)造函數(shù)中綁定或者使用class properties特性綁定,但bind和箭頭函數(shù)在特殊場景下需要使用,即需要傳遞額外參數(shù)的情況。
<button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button>
<button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>