React 事件处理程序中 this 的值
Posted
技术标签:
【中文标题】React 事件处理程序中 this 的值【英文标题】:Value of this in React event handler 【发布时间】:2015-06-26 05:48:04 【问题描述】:由于某种原因,this 的值在反应事件处理程序中丢失了。阅读文档,我认为 react 在这里做了一些事情以确保将其设置为正确的值
以下内容不像我预期的那样工作
import React from 'react';
export default class Observer extends React.Component
handleClick()
console.log(this); //logs undefined
render()
return (
<button onClick=this.handleClick>Click</button>
);
但这确实:
import React from 'react';
export default class Observer extends React.Component
handleClick()
console.log(this); //logs Observer class instance
render()
return (
<button onClick=this.handleClick.bind(this)>Click</button>
);
React 和 ES6 对我来说是新的,但这似乎不是正确的行为?
【问题讨论】:
为什么不是正确的行为? jsx 是否过多地掩盖了您为onClick
创建的函数?
这与 ES6 无关。它在 ES5 中也不起作用。
@Bergi Accepted 答案另有说明。在 ES5 中,您将使用 React.createClass 并且您不必手动绑定。所以是的,这与使用 ES6 创建 React 组件的 OP 有关。
@StijndeWitt:当然,这是特定于框架的。可以编写一个(失败的)ES5 构造函数,它等效于没有React.createClass
的ES6 class
,并且仍然可以在ES6 中使用React.createClass
。
@Bergi 是的,但是 Facebook 本身提到了这个确切的问题,这是 从 React ES5 转换到 React ES6 时需要注意的事情之一,可以这么说与 ES6 无关,这很奇怪。另外,是的,它是特定于框架的,但这个问题被标记为reactjs
和react-jsx
是有原因的。问题是特定于框架的。最后,Facebook 建议 React.createClass
仅用于 ES5,并明确建议不要将其用于 ES6。
【参考方案1】:
如果您使用新的 class
语法,这对于 javascript 和 React 来说是正确的行为。
v0.13.0 中的autobinding feature does not apply to ES6 classes。
所以你需要使用:
<button onClick=this.handleClick.bind(this)>Click</button>
或其他技巧之一:
export default class Observer extends React.Component
constructor()
super();
this.handleClick = this.handleClick.bind(this);
handleClick()
/* ... */
render()
return <button onClick=this.handleClick>Click</button>
【讨论】:
编辑了您的答案,以阐明自动绑定在所有版本的 React 中继续与 React.createClass 一起使用。 感谢本的澄清。 请注意,在您链接的文档中,您还提供了另一个使用 ES7 类属性创建箭头函数处理程序的解决方案,例如handleClick = (e) =>
,然后在构造函数或任何地方都不需要 bind
调用。
【参考方案2】:
公认的答案很好,我在 ES6 中使用了很多,但我只想添加另一个我们在 ES7 中拥有的“更现代”的解决方案(在 React component class auto-binding notes 中提到):使用箭头函数作为 @987654322 @,那么你不需要在任何地方绑定或包装你的处理程序。
export default class Observer extends React.Component
handleClick = (e) =>
/* ... */
render()
return <button onClick=this.handleClick>Click</button>
这是迄今为止最简单、最干净的解决方案!
【讨论】:
onClick=e => this.handleClick(e)
不是更有效率吗?我相信它和this.handleClick = this.handleClick.bind(this)
几乎是一样的,只是后者更多的是双打。
我的示例没有使用.bind()
,它将粗箭头定义为类属性并简单地将其传递给回调属性。我认为这比在回调道具的每次渲染中定义箭头函数更有效,并且输入更少,特别是如果您想在渲染函数的多个位置使用处理程序。【参考方案3】:
正如其他人所说,React 在使用 ES6 类时不会自动将方法绑定到实例。也就是说,我会养成在事件处理程序中始终使用箭头函数的习惯,例如:onClick=e => this.handleClick()
代替:onClick=this.handleClick.bind(this)
这是因为这意味着您可以在测试中用 spy 替换 handleClick 方法,这是您使用 bind 时无法做到的。
【讨论】:
在您的箭头示例中,handleClick 方法不会将 DOM 元素作为参数,除非您明确传递它对吗? 对,handleClick函数需要onClick=e => this.handleClick(e.target)
才能获取被点击的元素。以上是关于React 事件处理程序中 this 的值的主要内容,如果未能解决你的问题,请参考以下文章