簡體   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