【问题标题】:React - eval'ing event handlers within child component's scopeReact - 评估子组件范围内的事件处理程序
【发布时间】:2020-12-25 12:18:46
【问题描述】:

我的应用包含两个组件:“父”和“子”:

import React from "react";
import ReactDOM from "react-dom";

function Parent() {
  const t = "Parent";
  return (
    <div className="Parent">
      <Child
        content={
          <button type="button" onClick={() => eval("console.log(t);")}>
            Show t
          </button>
        }
      />
    </div>
  );
}

function Child(props) {
  const t = "Child";
  return props.content;
}

const rootElement = document.getElementById("root");
ReactDOM.render(
  <React.StrictMode>
    <Parent />
  </React.StrictMode>,
  rootElement
);

Link to Sandbox

Parent 将一些内容传递给 Child 并且 Child 呈现它。在我的示例中,内容是一个按钮。这个按钮有一个 onClick 处理程序,当它被点击时打印一些变量t 的值。由于我无法控制的原因,处理程序使用eval 并在父组件的范围内进行评估(如果单击按钮,您可以看到它记录“父”,这是父组件内t 的值) . 但是,我需要将 t 的范围限定在 Child 的范围内(以便在单击按钮时记录“Child”)。有没有办法做到这一点?

我对 JS 范围规则不是很清楚,但据我了解,直接调用 eval 时具有本地范围。但是我事先不知道 Child 的内容,所以我不能在 Child 本身内部调用它。另外,我不能完全避免使用 eval,因为处理程序将始终作为字符串传递给组件。


编辑:我可以使用React.cloneElement 将处理程序包装在子组件内的 eval 中,如下所示:

function Child(props) {
  const t = "Child";
  return React.cloneElement(props.content, {onClick: eval(props.content.props.onClick)});
}

这可行,但如果内容具有嵌套组件,则它是站不住脚的 - 我将不得不通过它们进行递归,它会变得混乱。

【问题讨论】:

  • 为什么不在子组件中指定按钮?
  • @Ashu,Child 组件只是一个包装器组件,它的内容可以是任何东西,我事先并不知道。
  • 可能您已经找到了实现此目标的最佳方法,您可以将解决方案粘贴到您自己的答案中

标签: javascript reactjs scope eval scoping


【解决方案1】:

您能否将content 设为变量t 的函数,然后在要关联该变量的范围内的组件内调用它?
我的意思是类似下面的代码:

function Parent() {
  const t = "Parent";
  return (
    <div className="Parent">
      <Child
        content={(
           t // <-------------------- note that it is a function now
        ) => (
          <button type="button" onClick={() => eval("console.log(t);")}>
            Show t
          </button>
        )}
      />
    </div>
  );
}

function Child(props) {
  const t = "Child";
  return props.content(t); // <--------------------- calling it here, so it see t from child component
}

编辑:我可以使用 React.cloneElement 将处理程序包装在子组件内的 eval 中 这可行,但如果内容具有嵌套组件,则站不住脚 - 我将不得不递归 > 通过它们,它会变得混乱。

它也不应该引起递归问题,因为您将传递给该函数的变量t 将在该函数的范围内,因此在那里创建的所有组件都应该看到它(就像现在发生在您的@ 987654328@ 组件,可以看到来自Parent 范围的变量。)

【讨论】:

  • 感谢您的回复@Bohdan。我可以将一个函数传递给 props.content,但它必须是字符串的形式。在我的实际应用中,props.content 的值是一个具有属性名称、属性和子项的对象。在 Child 中,我递归地将 React.createElement 应用于此对象,以将其转换为 React 元素。您能否建议使用此对象的替代方法?
  • 我在想我可以标记需要 eval 的属性,以便在我将 React.createElement 应用于 Child 中的 props.content 对象时识别和评估这些道具。这是一个Sandbox,可以更好地说明问题。我正在使用callt 传递给调用React.createElement 的函数。这可行,但现在onClick 回调必须使用this 关键字来引用t,即'() =&gt; {console.log(this.t}'
  • 抱歉,这么晚才回复,因为假期我不在电脑附近。我设法创建了一个示例,在该示例中我不使用此 codesandbox.io/s/eval-with-nested-component-forked-xpm5m?file=/… 取而代之的是,我正在对名为 scope 的对象进行字符串化,并创建一个新函数作为 onClick 处理程序。请注意,我使用的是 window.Function 而不是 eval,因为它是在文档中编写的,它比 eval 更快、更安全。 developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…!
  • 另外注意,我把你原来对象中的onClick的名字改成了onClickHandler,因为当我使用onClick的时候,有一个奇怪的循环和window.Function(same as eval),而不是看到原来的方法saw 方法,我将其定义为 hydrate 函数中的 onclick 处理程序。
猜你喜欢
  • 2015-11-28
  • 2018-08-18
  • 1970-01-01
  • 2017-05-04
  • 1970-01-01
  • 1970-01-01
  • 2011-07-05
  • 2021-01-12
  • 2018-01-25
相关资源
最近更新 更多