你如何在 React 中截断 html 文本?

问题描述

我正在尝试将以下 html 截断为 5 个字符:

<b>Hello</b> how are you today?

我正在寻找的结果是:

你好

但是,如何忽略截断中的 html 标记,以免导致以下结果?

<b>He

我使用的是 html 解析器,所以我无法在使用后截断字符串。这是我的代码,不用说,它不起作用!

import React from 'react';
import parse from 'html-react-parser';
import Typography from '@material-ui/core/Typography';


const Message= () => {
  const message= "<b>Hello</b> how are you today?"
  const messageParsed = parse(message);

  return (
          <Typography variant="body2">
            {messageParsed.substr(0,5)}
          </Typography>
  );
};

export default Message;

正确的方法是什么?

非常感谢,

凯蒂

解决方法

您可以使用 Range保持 html 结构

要获取特定长度的 html,请调用下面的 htmlToLength(html,length)

您还可以通过调用 htmlToNodeWithLength(html,length) 来获取 DocumentFragment。

该算法的核心是 findRangeWithLength(range,length),它从末尾(递归地)缩小 range,直到它具有给定的 length

function htmlToLength(html,length) {
  const trimmedNode = htmlToNodeWithLength(html,length);

  const container = document.createElement("div");
  container.appendChild(trimmedNode);
  return container.innerHTML;
}

function htmlToNodeWithLength(html,length) {
  // Only for measurement. Never added to DOM.
  const container = document.createElement("div");
  container.innerHTML = html;

  const fullRange = document.createRange();
  fullRange.setStart(container,0);
  fullRange.setEnd(container,1);

  const range = findRangeWithLength(fullRange,length);
  return range.cloneContents();
}

function findRangeWithLength(range,length) {
  if (rangeLength(range) < length) return range;

  // Find the childNode with at least length content.
  for (const childNode of range.endContainer.childNodes) {
    range.setEnd(childNode,lastEndOffset(childNode));
    if (rangeLength(range) >= length) {
      return findRangeWithLength(range,length);
    }
  }

  // There are no child nodes long enough. It's a text node.
  const diff = length - rangeLength(range) + range.endOffset;
  range.setEnd(range.endContainer,diff);
  return range;
}

function lastEndOffset(node) {
  return node.childNodes.length || node.textContent.length;
}

function rangeLength(range) {
  return range.toString().length;
}

const html = "<p>No <span></span><b>Hello</b> <i>World</i></p>";
const length = 7;
const trimmedNode = htmlToNodeWithLength(html,length);

document.querySelector(".raw-input").textContent = html;
document.querySelector(".trimmed").appendChild(trimmedNode);
document.querySelector(".length").textContent = length;
document.querySelector(".input").innerHTML = html;
document.querySelector(".raw-output").textContent = htmlToLength(html,length);
<h2>Raw HTML input</h2>
<div class="raw-input"></div>
<h2>Rendered Input</h2>
<div class="input"></div>
<h2>Rendered output to length <span class="length">?</span></h2>
<div class="trimmed"></div>
<h2>Raw HTML output</h2>
<div class="raw-output"></div>

,

我的理解是你有一个HTML文本,需要进行以下操作

  1. 删除 HTML 标签
  2. 将第 1 步之后的字符串截断为 5 个字符。

在这种情况下,可以使用正则表达式来完成。

import React from "react";
import "./styles.css";

export default function App() {
  const message = "<b>Hello</b> how are you today?";
  const messageString = message.replace(/<(.|\n)*?>/g,'');

  const subText = messageString.substring(0,5);

  return <div>{subText}</div>;
}

检查 here 以获得工作样本。

查看 thisthis 链接以了解有关如何从 JS 中的字符串中删除 HTML 标签的更多信息。

关于包 html-react-parser 这不返回字符串因此 substring 方法将不起作用。它返回一个数组。在您的情况下,行 parse(<b>Hello</b> how are you today?); 将返回以下内容 enter image description here