简体   繁体   English

利用<component />带有危险的SetInnerHTML

[英]Use <Component /> with dangerouslySetInnerHTML

First off, I did try looking at a few similar questions but couldn't find one that best matched my case, where I need multiple arguments.首先,我确实尝试查看一些类似的问题,但找不到与我的情况最匹配的问题,我需要多个 arguments。

I have a variable that contains raw HTML data, including a long paragraph that I need to truncate if it's too long.我有一个包含原始 HTML 数据的变量,包括一个长段落,如果它太长我需要截断。 To make life simpler I'm using a module to handle this ( read-more-react ).为了让生活更简单,我使用了一个模块来处理这个( read-more-react )。 read-more-react requires a few fields to be filled out including the text itself, and a few other fields like min and max characters before truncating. read-more-react 需要填写一些字段,包括文本本身,以及截断之前的一些其他字段,例如最小和最大字符。

The suggested way from Gatsby to parse raw HTML data is to use dangerouslySetInnerHTML , but I'm having some issues with including my component. Gatsby 解析原始 HTML 数据的建议方法是使用dangerouslySetInnerHTML ,但我在包含我的组件时遇到了一些问题。 I tried using the read-more-react module without dangerouslySetInnerHTML .我尝试使用 read-more-react 模块而不使用dangerouslySetInnerHTML It works, but only outputs the raw HTML " <h1>A title</h1><p>Some copy...</p> etc) without actually parsing it.它可以工作,但只输出原始 HTML " <h1>A title</h1><p>Some copy...</p> etc) 而不实际解析它。

Instead, I tried this;相反,我尝试了这个;


    <div
      className="md container"
      dangerouslySetInnerHTML={{
        __html: `
          <ReadMoreReact
            text=${htmlContent}
            min="180"
            ideal="190"
            max="200"
            readMoreText="Read more"
          />
        `,
      }}
    />

But I get a weird output;但我得到一个奇怪的 output;

A title标题

Some copy一些副本

min="180" ideal="190" max="200" readMoreText="Read more" />

So this clearly isn't working.所以这显然是行不通的。 Can anyone suggest a workaround?任何人都可以提出解决方法吗?

read-more-react seems to handle only text, not html. read-more-react似乎只处理文本,而不是 html。
You should probably parse your html string before passing it to the ReadMoreReact component, in order to separate the paragraph from the rest and extract its text content.您可能应该在将 html 字符串传递给 ReadMoreReact 组件之前对其进行解析,以便将段落与 rest 分开并提取其文本内容。
Actually, you can do that using the DOM:实际上,您可以使用 DOM 做到这一点:

 const htmlString = "<h1>This is the title</h1><p>The innerText property of the HTMLElement interface represents the \"rendered\" text content of a node and its descendants. As a getter, it approximates the text the user would get if they highlighted the contents of the element with the cursor and then copied it to the clipboard.</p>" const dummyElement = document.createElement('div') dummyElement.innerHTML = htmlString; const titleText = dummyElement.querySelector('h1').innerText const pText = dummyElement.querySelector('p').innerText console.log('title ==>', titleText); console.log('p ==>', pText);

The problem is that dangerouslySetInnerHTML expects a string of normal HTML elements.问题是dangerouslySetInnerHTML需要一串正常的 HTML 元素。 Instead, you're attempting to pass in a React node which is invalid HTML(in addition ReadMoreReact returns an array of strings, which is also invalid).相反,您试图传入一个无效 HTML 的 React 节点(此外ReadMoreReact返回一个字符串array ,这也是无效的)。 Instead, you can use their trimText utility function, which will do what you're expecting.相反,您可以使用他们的trimText实用程序 function,它可以满足您的期望。

These examples use some advanced ES5+ functions:这些示例使用了一些高级 ES5+ 函数:

Working example (using hooks):工作示例(使用钩子):

编辑修剪 HTML 文本

import React from "react";
import { render } from "react-dom";
import trimText from "./utils/trimText";
import "./styles.css";

const htmlText =
  "<h2 style='display:inline;'>Lorem ipsum</h2> dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.";

function App() {
  const [state, setState] = React.useState({
    showOriginalHTML: false,
    originalHTML: htmlText,
    trimmedHTML: trimText(htmlText, 20, 200)[0]
  });

  const handleShowText = React.useCallback(() => {
    setState(prevState => ({
      ...prevState,
      showOriginalHTML: !prevState.showOriginalHTML
    }));
  }, [setState]);

  return (
    <div className="container">
      <div
        className="text"
        dangerouslySetInnerHTML={{
          __html: `${
            !state.showOriginalHTML ? state.trimmedHTML : state.originalHTML
          }`
        }}
      />
      <button className="read-more" onClick={handleShowText}>
        {!state.showOriginalHTML ? "read more" : "show less"}
      </button>
    </div>
  );
}

render(<App />, document.getElementById("root"));

Working example (using classes):工作示例(使用类):

编辑修剪 HTML 文本 - 类

import React from "react";
import { render } from "react-dom";
import trimText from "./utils/trimText";
import "./styles.css";

const htmlText =
  "<h2 style='display:inline;'>Lorem ipsum</h2> dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.";

class App extends React.Component {
  state = {
    showOriginalHTML: false,
    originalHTML: htmlText,
    trimmedHTML: trimText(htmlText, 20, 200)[0]
  };

  handleShowText = () =>
    this.setState(prevState => ({
      showOriginalHTML: !prevState.showOriginalHTML
    }));

  render = () => {
    const { originalHTML, showOriginalHTML, trimmedHTML } = this.state;

    return (
      <div className="container">
        <div
          className="text"
          dangerouslySetInnerHTML={{
            __html: `${!showOriginalHTML ? trimmedHTML : originalHTML}`
          }}
        />
        <button className="read-more" onClick={this.handleShowText}>
          {!showOriginalHTML ? "read more" : "show less"}
        </button>
      </div>
    );
  };
}

render(<App />, document.getElementById("root"));

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

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