翻译参考自: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“的错误,如下图所示:
这是因为当我们调用以这种方式绑定到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