使用 .replace() 方法可以替代 innerHTML 吗?

Posted

技术标签:

【中文标题】使用 .replace() 方法可以替代 innerHTML 吗?【英文标题】:Is there any alternative to innerHTML with .replace() method? 【发布时间】:2021-11-16 14:15:06 【问题描述】:

我知道使用innerhtml 的缺点。但在我的情况下,innerHTML 看起来是不可避免的。要么是不必要的复杂,要么是不可能的(我不这么认为......)

这是我的代码:

function identifier(reg, className) 
  const regex = new RegExp(reg, "gi");
  const p2 = document.querySelectorAll("p");
  p2.forEach((ps) => 
    ps.innerHTML = ps.innerHTML.replace(
      regex,
      (match) => `<span class="$className">$match</span>`
    );
  );

identifier("[^<>]+?:", "identifier");

在不使用innerHTML 的情况下,还有其他更安全的方法吗?

提前致谢!

编辑:p 元素开头不包含任何其他标签。它只包含文本。但是我想用上面的函数给它添加spans

在此我使用 RegExp 和 replace() 方法将所有标识符(例如:姓名、电子邮件)设置为 span 以分别进行样式设置。像 John Doe 这样的值没有样式化。

【问题讨论】:

我想不出一个简单的方法来做到这一点。您必须为匹配项周围的文本部分创建新的文本节点,然后为匹配项创建跨度节点。 如果段落中已经有 HTML 标签,您将不得不浏览它们。 我认为您可以通过遍历不在标签内的文本节点来做到这一点。 我的第一个想法:为什么会在 javascript 中发生这种情况?这看起来像是在生成原始 HTML(即服务器端)时应该做的事情。但除此之外,您的代码缺少太多上下文,无法给出一个好的答案。当然,对于任何可能的 HTML 内容,如果没有 innerHTML 也可以做到这一点,但如果实现可以限制在特定场景中,例如匹配总是在不包含任何其他 HTML 的段落。 “要了解我真正打算做什么,请看这支笔(注意它会改变)” - 最后一部分就是为什么你不应该 仅通过外部平台提供相关信息。您的问题的minimal reproducible example 直接属于您的问题。 【参考方案1】:

有了您的附加信息,这相对容易:

p2.forEach((ps) => 
  // Get text of paragraph removing any HTML
  const text = ps.textContent;

  // Look for colon      
  const colon = text.indexOf(':');
  
  // Skip if there is no colon
  if (colon === -1) 
    return;
  

  // Delete content of paragraph
  while (ps.lastChild) 
    ps.removeChild(ps.lastChild);
  

  // Extract texts before (and including) colon and after colon
  const labelText = text.substring(0, colon + 1);
  const otherText = text.substring(colon + 1);

  // Create span with text before colon
  const label = document.createElement('span');
  label.className = className;
  label.appendChild(document.createTextNode(labelText));

  // Create new text node with text after colon
  const otherTextNode = document.createTextNode(otherText);

  // Add both as new children of the paragraph
  ps.appendChild(label);
  ps.appendChild(otherTextNode);
);

当然比使用innerHTML要长,因为我们基本上是在重写正则表达式和浏览器的HTML解析器正在做的事情。

【讨论】:

以上是关于使用 .replace() 方法可以替代 innerHTML 吗?的主要内容,如果未能解决你的问题,请参考以下文章

错误重载方法值 regexp_replace 与替代品

替代 String.Replace

在 text 或 ntext 数据类型上替代 REPLACE

在 text 或 ntext 数据类型上替代 REPLACE

INN实现深入理解

replace