繁体   English   中英

function 与 class 反应组件中的事件处理程序的“this”上下文不同

[英]'this' context different for event handlers in function vs class react components

为什么'this'(上下文)会根据我在反应中使用功能组件还是 class 组件而有所不同? 我了解绑定的工作原理,并且我的处理程序将采用 onclick 处理程序的上下文(或者它在 onclick 中使用),但我不明白为什么这两种情况的值不同。 功能组件打印 window object 而 class 组件打印未定义。

如何定义合成 onclick 事件? 它的背景是什么? 它的回调有什么作用?

export default function App() {
  const handleClick = function () {
    console.log(this);
  };

  return (
    <div className="App">
      <button onClick={handleClick}>HandleClick Functional</button>
      <Toggle />
    </div>
  );
}

class Toggle extends React.Component {
  handleClick() {
    console.log(this);
  }

  render() {
    return <button onClick={this.handleClick}>HandleClick Class</button>;
  }
}

代码框链接: https://codesandbox.io/s/onclick-context-test-ievog6?file=/src/App.js

TL;DR - 这看起来像 CodeSandbox 的一个错误。 您的 React function 组件代码最终以非严格模式运行,这导致您的this值默认为全局 object 而不是应为的undefined

这种行为很奇怪。 但就像qrsngky在上面的评论中正确指出的那样,问题主要与严格模式有关,并且是 CodeSandbox 如何进行错误处理的结果。 下面我概述了我对您的代码为何如此运行的观察。

使用function关键字声明的函数有自己的this值(它们自己的“this 绑定”)。 如何确定this值取决于 function 的执行方式。 .call( .call().apply()等方法能够为它们执行的 function 设置this值。

在严格模式代码中,使用fn.apply(undefined)会导致执行 function fn并将fn中的this值设置为undefined 但是,在非严格模式代码中,使用fn.apply(undefined)会导致this值设置为全局 object ,在浏览器中为window object。 当 React 调用您的onClick处理程序 function ( func ) 时,它通过执行func.apply(context, ...)来调用它,并将context设置为undefined (您可以通过调试器看到这一点):

在此处输入图像描述

此时,您可能会认为您的代码在任何地方都没有使用"use strict"指令,因此当您的 function 使用this of undefined调用时,它默认为全局 object window 但是,它并不像那样简单;)。 虽然看起来您的任何代码都没有在严格模式下运行,但实际上它被归类为严格模式代码。 那是因为ES6 模块(您编写反应代码的内容) 会自动在 strict-mode 下运行 同样, 类也自动以严格模式运行 所以这就引出了一个问题,即为什么你的代码显示window那么你的代码是否真的应该在严格模式下运行。

编写 React 代码时,需要将其转换为浏览器可以理解和执行的代码。 似乎发生的事情是,当您的反应代码被转译时,CodeSandbox 在您的反应代码周围添加了一个try-finally 包装器(您可以使用禁用源映射的调试器看到这一点):

try {
  "use strict";
   ...
   function App() {
     const handleClick = function() {
       console.log(this);
     }
   }
...
} finally {
 ...
}

我们可以看到 CodeSandbox 尝试将您的代码包装在 try-finally 块中,其中try块以“严格模式”运行,以尝试匹配最初编写代码的 ES6 模块自动应用的相同严格模式行为。但是,在与 function 无关的块{}中应用"use strict"对代码的严格性没有影响(有关严格模式的规则,请参见 此处)。 因此,CodeSandbox 应用的 try-finally 包装器最终会以非严格/草率模式运行您的代码。 当 React 使用undefined调用您的 onClick 处理程序时,这将导致thiswindow

另一方面,您的class仍然按预期工作,因为在转译的代码中它仍然是class ,因此围绕类的严格模式行为仍然存在,因此您会看到undefined的预期。


但是,在使用 React 功能组件时,您不需要参考this ,而是可以使用诸如useState()类的钩子来管理诸如 state 之类的东西。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM