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