翻译参考自:React and ES6 - Part 3, Binding to methods of React class (ES7 included)

在React进行事件方法绑定的时,如下面的代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
import React , {Component} from 'react'

class user extends Component{
    render(){
       return <button onClick={this.sayhello} >open hello</button>
    }

    sayhello(){
        console.log('hello world')
        console.log(this.props)
    }
}

export default user

我们将会得到“TypeError: Cannot read property ‘props’ of null“的错误,如下图所示: error

这是因为当我们调用以这种方式绑定到this的方法时,没有将函数上下文绑定到组件的实例上。这是Javascript的默认行为而且是可以明确预期到的。

React团队在实现支持ES6时不支持自动绑定,你在这篇博客中找到更多关于这样做的原因。

下面将介绍几种不同的方式实现,在JSX中使用ES6语法调用class method。

方法一、 使用Function.prototype.bind()

如下面的代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
// 使用bind()
class user extends Component{
    render(){
       return <button onClick={this.sayHello.bind(this)} >open hello</button>
    }

    sayHello(){
        console.log(this.props)
    }
}

任何ES6类的方法都是纯JavaScript函数,并从Function prototype继承了bind()方法,所以当我们调用sayHello方法时,this将会指向我们的组件实例。在MDN article可以找到更多的相关信息。

方法二、 使用在constructor中定义的方法

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
// 使用构造函数定义的方法
class user1 extends Component{
    constructor(props){
        super(props)
        this._sayHello = ()=> this.sayHello();
    }

    sayHello(){
        console.log(this.props)
    }

    render(){
        return (<button onClick={this.sayHello}>open hello 1</button>)
    }
}

这种方式中,不再需要在JSX中使用bind(),但会使构造函数更加膨胀。

方法三、使用箭头操函数和构造函数

ES6箭头函数会保留定义时的this上下文,即当调用箭头函数时,函数体内的this对象,就是定义时所在的对象,而不是调用时所在的对象。所以可以利用这个特性,并在构造函数中重新定义sayHello方法。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
// 箭头函数 + 构造函数
class user extends Component{
    constructor(props){
        super(props)
        this._sayHello = ()=> this._sayHello()
    }

    sayHello(){
        console.log(this.props)
    }

    render(){
       return <button onClick={this._sayHello.bind(this)} >open hello3</button>
    }
}

方法四、使用箭头函数和ES6类属性

可以通过使用箭头函数和ES6类属性语法:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
// 箭头函数 + ES属性语法
class user extends Component{
    sayHello = ()=>{
        console.log(this.props)
    }

    render(){
       return <button onClick={this.sayHello} >open hello4</button>
    }
}

源码下载

上面出现的代码下在地址: github

参考