piz*_*r0b 26 javascript ecmascript-6 reactjs
令我困惑的是为什么当我定义一个反应组件类时,this
对象中包含的值在类中定义的方法(this
在生命周期方法中可用)中是未定义的,除非我使用.bind(this)
或定义方法使用箭头函数,例如在以下代码this.state
将在renderElements
函数中未定义,因为我没有用箭头函数定义它并且没有使用.bind(this)
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>
);
}
}
Run Code Online (Sandbox Code Playgroud)
然后在下面的示例中,我不需要使用.bind(this)
或箭头函数,this
在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();
Run Code Online (Sandbox Code Playgroud)
http://jsbin.com/cadoduxuye/edit?js,console
澄清一下,我的问题是两部分.一)为什么在第二个代码示例中我不需要调用.bind(this)
该speak
函数,但我在函数的React组件中执行,renderElements
以及为什么生命周期方法(render,componentDidMount等)已经可以访问该类' this
对象,但renderElements
没有.
在React文档中,它说明如下
[React Component Class]方法遵循与常规ES6类相同的语义,这意味着它们不会自动将其绑定到实例.
但显然他们确实如此,正如我发布的第二个代码示例所示.
更新
前两个注释中的两个链接都显示了React类的工作示例,.bind(this)
它不使用类方法,并且工作正常.但仍然在文档中明确表示您需要绑定您的方法,或使用箭头函数.在一个使用gulp和babel的项目中,我可以重现.这可能意味着浏览器有更新的东西?
更新2
我的初始代码示例this.renderElements()
直接在render函数中调用.这将按预期工作而不绑定函数,或使用箭头函数定义它.当我将函数作为onClick
处理程序时,会出现问题.
更新3
当我将函数作为
onClick
处理程序时,会出现问题.
事实上,这根本不是问题.this
传递给onClick处理程序时的更改上下文,这就是JS的工作原理.
Fel*_*ing 13
该值this
主要取决于函数的调用方式.给定d.speak();
,this
将引用d
因为该函数被称为"对象方法".
但是<div>{this.renderElements}</div>
你没有调用这个功能.您正在将该函数传递给React,它将以某种方式调用它.当它被调用时,React不知道函数"属于"哪个对象,因此无法为其设置正确的值this
.绑定解决了这个问题
我实际上认为你真正想要的是
<div>{this.renderElements()}</div>
// call function ^^
Run Code Online (Sandbox Code Playgroud)
即将函数作为对象方法调用.然后你不必绑定它.
查看MDN以了解更多信息this
.
Phi*_*yen 12
组件中的事件处理程序不会像其他方法(生命周期方法......)那样自动绑定到组件实例.
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
Run Code Online (Sandbox Code Playgroud)
查看此示例以了解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
Run Code Online (Sandbox Code Playgroud)
您可以查看此文章以获取更多信息.
ES6类中的函数 - @Felix Kling很好地解释了这种情况.每次在对象上调用函数时,都this
指向该对象.
React.Component中的生命周期方法 - 每当React实例化您的组件时,就像myComponent = new MyComponent()
它知道调用生命周期方法的对象,即myComponent.因此,在生命周期方法中myComponent.componentDidUpdate()
可以this
使用简单的调用componentDidUpdate
.其他生命周期方法也是如此.
处理程序和在React.Component束缚 - this.state
是undefined
的,因为this
实际上是window
-登录一下看看.原因是React在全局上下文中调用处理程序,除非您将处理程序绑定到另一个覆盖的上下文 window
(请参阅@Phi Nguyen的答案).我认为他们这样做是为了让你更灵活,因为在复杂的应用程序中,你的处理程序可能来自另一个通过道具传递的组件,然后你想有可能说:"嘿,React - this
不是我的组件,但它是父".
React的文档是一个误导性的,当它说
方法遵循与常规ES6类相同的语义,这意味着它们不会自动将其绑定到实例.
他们的意思是
var dog = new Dog('Mitzie');
speak = d.speak;
dog.speak() // this will be dog, because the function is called on dog
speak() // this will be window, and not dog, because the function is not bound
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
7808 次 |
最近记录: |