【问题标题】:How to access data displayed by dangerous html如何访问危险 html 显示的数据
【发布时间】:2021-07-07 21:23:51
【问题描述】:

我在反应钩子中使用危险的 HTML 显示表格

现场演示:live demo code sand box

数据看起来像这样

export const json = [
  {
    template: `
    <div ref={tableRef} className="table">
    <table>
      <thead>
        <tr>
          <th>#</th>
          <th>First Name</th>
          <th>Last Name</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td>1</td>
          <td>Mark</td>
          <td>Otto</td>
        </tr>
      </tbody>
    </table>
  </div>
    `
  }
];

这里是使用危险HTML 显示数据

......

export default function App(props) {
  const tableRef = useRef("");
  let tables = data.json;

  return (
    <div className="App">
      <input type="text" />
      <div
        ref={tableRef}
        dangerouslySetInnerHTML={{ __html: tables[0].template }}
      />
    </div>
  );
}

问题:我需要做什么才能访问此表中的表数据(假设我想在输入更改时更改名称)?

【问题讨论】:

    标签: javascript reactjs react-hooks use-ref template-strings


    【解决方案1】:

    首先,小心这种方法,it's an easy way to open your users to XSS attacks

    一般来说,从代码中设置 HTML 是有风险的,因为很容易在不经意间让您的用户受到跨站脚本 (XSS) 攻击。所以,你可以直接从 React 中设置 HTML,但你必须输入 dangerouslySetInnerHTML 并使用 __html 键传递一个对象,以提醒自己这是危险的。

    也就是说,在这种情况下,您将不得不手动访问和管理危险设置的 HTML。 由于这是“副作用”的教科书示例,请在 useEffect 内进行管理。

    在 React 组件中获取数据、设置订阅以及手动更改 DOM 都是副作用的示例。 - https://reactjs.org/docs/hooks-effect.html

    假设您为输入创建了一个状态值iVal,您可以像这样更改表格文本:

      // ... New state:
      const [iVal, setIVal] = React.useState("");
    
      // ...
      React.useEffect(() => {
        console.log(tableRef);
    
        if (iVal) {
          tableRef.current
            .getElementsByTagName("tbody")[0]
            .getElementsByTagName("td")[1].innerHTML = iVal;
        }
      }, [iVal, tableRef]);
    
      // ... Updated input:
      <input
        type="text"
        value={iVal}
        onChange={(e) => setIVal(e.target.value)}
      />
      // ...
    

    因此,由于dependency array ([iVal, tableRef]),您的useEffect 将在iVal(或tableRef)更改时更新。

    从您的代码盒中派生的工作示例:

    【讨论】:

    • 是否可以将getElement by id 与useref 一起使用?
    • 当这样使用时,您将获得一个 DOM 节点,因此 getElemenyById 或任何其他 'getElement' 或 'querySelector' 方法也应该可以工作。我只是使用了“TagName”,因为我不想编辑 HTML 字符串。
    • 我试过这样let chatta = tableRef.current.getElementById("fname"),但我收到错误TypeError: tableRef.current.getElementById is not a function
    • 我的错,是的,您应该可以访问此处列出的所有内容 developer.mozilla.org/en-US/docs/Web/API/Element,其中不包括 getElementById。因此,要通过 ID 获取,您必须使用 tableRef.current.querySelector("#name")
    【解决方案2】:

    按照您的设置方式,从技术上讲,您可以使用tableRef.current 间接访问表数据,这将为您提供对 HTMLDivElement 对象的引用,但您几乎肯定最好将此代码重构为 不危险地使用SetInnerHTML。

    相反,您可能需要考虑将表数据存储为对象数组,例如:

    [{firstName: "Mark", lastName: "Otto"}, {firstName: "Jack", lastName: "Antonoff"}]
    

    您可以使用useState hook 存储和更新它。要循环显示数据,您可以使用简单的映射函数 detailed in the React docs 并为数组中的每个元素输出一个表格行。

    Simple working example here.

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-11-29
      • 1970-01-01
      • 2013-03-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多