用react進行開發組件時,我們需要關注一下組件內部方法this的指向,react定義組件的方式有兩種,一種為函數組件,一種為類組件,類組件內部可以定義一些方法,這些方法的this需要綁定到組件實例上,小編這里總結了一下,一共有四種方案:
第一種方案,在構造函數內部使用bind綁定this,這樣做的好處是,避免每次渲染時都要重新綁定,代碼如下:
import React, {Component} from 'react' class Test extends React.Component { constructor (props) { super(props) this.state = {message: 'Allo!'} this.handleClick = this.handleClick.bind(this) } handleClick (e) { console.log(this.state.message) } render () { return ( <div> <button onClick={ this.handleClick }>Say Hello</button> </div> ) } } |
第二種方案同樣是用bind,但是這次不再構造函數內部使用,而是在render函數內綁定,但是這樣的話,每次渲染都需要重新綁定,代碼如下:
import React, {Component} from 'react' class Test extends React.Component { constructor (props) { super(props) this.state = {message: 'Allo!'} } handleClick (name, e) { console.log(this.state.message + name) } render () { return ( <div> <button onClick={ this.handleClick.bind(this, '趙四') }>Say Hello</button> </div> ) } } |
第三種方案是在render函數中,調用方法的位置包裹一層箭頭函數,因為箭頭函數的this指向箭頭函數定義的時候其所處作用域的this,而箭頭函數在render函數中定義,render函數this始終指向組件實例,所以箭頭函數的this也指向組件實例,代碼如下:
class Test extends React.Component { constructor (props) { super(props) this.state = {message: 'Allo!'} } handleClick (e) { console.log(this.state.message) } render () { return ( <div> <button onClick={ ()=>{ this.handleClick() } }>Say Hello</button> </div> ) } |
以上這種方式有個小問題,因為箭頭函數總是匿名的,如果你打算移除監聽事件,是做不到的,那么怎么做才可以移除呢?看下一種方案。
第四種方案,代碼如下:
class Test extends React.Component { constructor (props) { super(props) this.state = {message: 'Allo!'} } handleClick = (e) => { console.log(this.state.message) } render () { return ( <div> <button onClick={ this.handleClick }>Say Hello</button> </div> ) } } |
不過,在Classes中直接賦值是ES7的寫法,ES6並不支持,你有兩種選擇,一種是配置你的開發環境支持ES7,一種使采用如下方式,下面這種方式是第四種方案的另外一種寫法,代碼如下:
class Test extends React.Component { constructor (props) { super(props) this.state = {message: 'Allo!'} this.handleClick = (e) => { console.log(this.state.message) } } render () { return ( <div> <button onClick={ this.handleClick }>Say Hello</button> </div> ) } |
另外注意:
class Toggle extends React.Component { constructor(props) { super(props); this.state = {isToggleOn: true}; // 這邊綁定是必要的,這樣 `this` 才能在回調函數中使用 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('example') ); |
你必須謹慎對待 JSX 回調函數中的 this,類的方法默認是不會綁定 this 的。如果你忘記綁定 this.handleClick 並把它傳入 onClick, 當你調用這個函數的時候 this 的值會是 undefined。
這並不是 React 的特殊行為;它是函數如何在 JavaScript 中運行的一部分。通常情況下,如果你沒有在方法后面添加 () ,例如 onClick={this.handleClick},你應該為這個方法綁定 this。
如果使用 bind 讓你很煩,這里有兩種方式可以解決。如果你正在使用實驗性的屬性初始化器語法,你可以使用屬性初始化器來正確的綁定回調函數:
class LoggingButton extends React.Component { // 這個語法確保了 `this` 綁定在 handleClick 中 // 這里只是一個測試 handleClick = () => { console.log('this is:', this); } render() { return ( <button onClick={this.handleClick}> Click me </button> ); } } |
如果你沒有使用屬性初始化器語法,你可以在回調函數中使用 箭頭函數:
class LoggingButton extends React.Component { handleClick() { console.log('this is:', this); } render() { // 這個語法確保了 `this` 綁定在 handleClick 中 return ( <button onClick={(e) => this.handleClick(e)}> Click me </button> ); } } |
使用這個語法有個問題就是每次 LoggingButton 渲染的時候都會創建一個不同的回調函數。在大多數情況下,這沒有問題。然而如果這個回調函數作為一個屬性值傳入低階組件,這些組件可能會進行額外的重新渲染。我們通常建議在構造函數中綁定或使用屬性初始化器語法來避免這類性能問題。
原文:https://blog.csdn.net/tonghonglei/article/details/88428195