React组件绑定this的四种方式
用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