令我感到困惑的是为什么当我定义一个反应组件类时,除非在类中使用箭头函数定义或使用该方法定义该方法,否则该类中定义的方法this中未定义对象中包含的值(this生命周期方法中可用).bind(this)。以下代码this.state将在renderElements函数中未定义,因为我没有使用箭头函数定义它并且未使用.bind(this)
this
.bind(this)
this.state
renderElements
class MyComponent extends React.Component { constructor() { super(); this.state = { elements: 5 } } renderElements() { const output = []; // In the following this.state.elements will be undefined // because I have not used .bind(this) on this method in the constructor // example: this.renderElements = this.renderElements.bind(this) for(let i = 0; i < this.state.elements; i ++){ output.push(<div key={i} />); } return output; } // .this is defined inside of the lifecycle methods and // therefore do not need call .bind(this) on the render method. render() { return ( <div onClick={this.renderElements}></div> ); } }
然后在下面的例子中,我不需要使用.bind(this)或箭头功能,this可作为预期speak功能
speak
class Animal { constructor(name) { this.name = name; } speak() { console.log(this.name + ' makes a noise.'); } } class Dog extends Animal { speak() { console.log(this.name + ' barks.'); } } var d = new Dog('Mitzie'); d.speak();
http://jsbin.com/cadoduxuye/edit?js,控制台
为了澄清,我的问题分为两部分。一)为什么在第二个代码示例中我不需要调用.bind(this)该speak函数,但是我在React组件中对该renderElements函数进行调用,二)为什么生命周期方法(render,componentDidMount等)已经可以访问该类?this对象,但renderElements不是。
在React文档中,它表示以下内容
[反应组件类]方法遵循与常规ES6类相同的语义,这意味着它们不会自动将其绑定到实例。
但是显然,它们确实可以做到,正如我发布的第二个代码示例所示。
更新资料
前两个注释中的两个链接都显示了一个不使用.bind(this)类方法的React类的工作示例,并且工作正常。但是仍然在文档中明确指出您需要绑定方法或使用箭头功能。在使用gulp和babel的项目中,我可以复制。难道浏览器已经更新了东西?
更新2
我的初始代码示例this.renderElements()直接在render函数中调用了。无需绑定功能或使用箭头功能定义它即可按预期工作。当我将函数用作onClick处理程序时,就会发生此问题。
this.renderElements()
onClick
更新3
当我将函数用作onClick处理程序时,就会发生此问题。
实际上,这根本不是问题。this更改的上下文传递给onClick处理程序时,这就是JS的工作方式。
组件中的事件处理程序不会像其他方法(生命周期方法…)那样自动绑定到组件实例。
class MyComponent extends React.Component { render(){ return ( <div onClick={this.renderElements}> {this.renderElements()} <-- `this` is still in side the MyComponent context </div> ) } } //under the hood var instance = new MyComponent(); var element = instance.render(); //click on div element.onClick() <-- `this` inside renderElements refers to the window object now
查看此示例以了解this更多信息:
class Animal { constructor(name) { this.name = name; } speak() { console.log(this.name + ' makes a noise.'); } } class Dog extends Animal { run(){ console.log(this.name + ' runs'); } speak() { console.log(this.name + ' barks.'); this.run(); <-- `this` is still in the Dog context return {onRun : this.run}; } } var d = new Dog('Mitzie'); var myDog = d.speak(); myDog.onRun() <-- `this` is now in the global context which is the `window` object
您可以查看本文以获取更多信息。