Published on
1237

使用 JavaScript 从字符串中去除HTML标记

Authors
  • avatar
    Name
    小辉辉
    Twitter

这是一篇翻译文章,原文地址:

Remove HTML markup from a String using JavaScript

在这篇教程中我们提供了两个途径来移除字符串中的html标签:第一个方法是基于正则表达式来实现的,第二个方法是基于DOM(文档对象模型)提供的方法来实现。

特别要说的是,当你要处理及其复杂的HTML结构的时候,DOM操作的实现通常来讲更加可靠且功能更强大。它能更好的处理边界情况和标签嵌套。然而,需要注意的是使用DOM对象操作会在内存中创建一个真实的DOM树,与正则表达式操作相比,这在处理很大的字符串时,会显得慢很多。DOM对象操作同样需要依赖浏览器环境(这并不适应用服务端js,也就是我们所谓的Nodejs)。

另一方面,在处理HTML结构结构都是已知的,明确的,不会很复杂的标签时,基于正则表达式的方案要使用起来会更简单快速。

使用 RegEx 删除 HTML 标签

让我们研究一下两个使用 JavaScript 从字符串中去除 HTML 标签的正则表达式模式,一个用于匹配 html 标签的开始和结束(使用尖括号),另一个用于匹配开始和结束标签(分别):

正则表达式:/(<([^>]+)>)/ig

  • (<([^>]+)>):这是正则表达式的主要部分。它匹配 HTML 的开始标签,后面跟着任意内容,然后是 HTML 的结束标记。
  • 内部部分([^>]+)匹配任何非 > 的字符序列,有效地捕获标签名称和属性。
  • ig:这些是正则表达式末尾的标志。i 使匹配不区分大小写,g 表示正则表达式将匹配输入字符串中的所有出现情况。
const htmlMarkup = '<b>www.DEVLABS.ninja</b> is awesome <img src="test.jpg"/>';
const cleanText = htmlMarkup.replace(/(<([^>]+)>)/ig, '');
// www.DEVLABS.ninja is awesome

正则表达式:/<\/?[^>]+(>|$)/ig

  • <\/?:这与开头的 < 匹配,后面跟着可选的 /,它既匹配html开头标签,也匹配html结尾标签。
  • [^>]+:匹配一个或多个非>的字符,对应标签名称和属性。
  • (>|$):这将捕获 >(开始标签的结尾)或字符串 ($) 的结尾,从而有效地确保整个标签匹配。
  • ig:与第一个示例相同
const htmlMarkup = '<b>www.DEVLABS.ninja</b> is awesome <img src="test.jpg"/>';
const cleanText = htmlMarkup.replace(/<\/?[^>]+(>|$)/ig, '');
// www.DEVLABS.ninja is awesome

两个正则表达式都有一些限制:

它们可能无法在所有情况下正确处理嵌套标签。 它们可能会因非标准或格式错误的 HTML 标签而出现意想不到的情况。 他们可能会无意中删除实际上不属于 HTML 标签的内容(如果有用于非 HTML 目的的尖括号)。

使用 DOM 对象操作删除 HTML 标签

为了更可靠、更准确地解析 HTML 和删除标签,建议使用专用的 HTML 解析器或 DOM 操作:

const html = '<b>www.www.DEVLABS.ninja</b> is awesome <img src="test.jpg"/>';
const div = document.createElement('div');
div.innerHTML = html;
const cleanText = div.textContent;
// www.DEVLABS.ninja is awesome

我们使用该textContent属性来提取不带 html 标记的文本。还有一个innerText属性可以给出相同的结果,但innerText性能要求更高,因为它会从节点返回当前可见文本,而textContent仅返回文本。

使用 DOM 操作方法也有一些缺点:

由于创建 DOM 元素需要有额外的开销,处理非常大的字符串时速度可能会比较慢。 需要浏览器环境(不适合服务器端 JavaScript)。

使用 DOMParser 对象删除 HTML 标签

删除 html 标签的最后一种方法涉及到 DOMParser 对象。它具有与 DOM 操作方法相同的优点和缺点:

const html = '<b>www.www.DEVLABS.ninja</b> is awesome <img src="test.jpg"/>';
const doc = new DOMParser().parseFromString(html, 'text/html');
const clean = doc.body.textContent || '';
// www.DEVLABS.ninja is awesome

虽然 DOMParser 它提供了更可靠的解决方案,但与正则表达式相比,对于非常大的字符串,它可能会更慢。在内存中创建 DOM 树需要更多开销。

我们还可以在使用了Node.js和Express的服务器端使用此方法,方法是使用JSDOM 库,它为服务器端 JavaScript 提供了一个模拟的浏览器环境。

下面是如何在 Express 路由处理程序中使用 DOMParser 的示例:

const express = require('express');
const { JSDOM } = require('jsdom');

const app = express();
const port = 3000;

app.get('/', (req, res) => {
  const html = req.query.html || '';
  const dom = new JSDOM(html);
  const clean = dom.window.document.body.textContent;

  res.send(`Cleaned text: ${clean}`);
});

app.listen(port, () => {
  console.log(`Server is running on port ${port}`);
});

总结

对于简单的html标签移除场景,使用正则表达式足够了,因为它又快有方便;对于复杂的html标签操作,浏览器端考虑使用DOM对象活着DOMParser对象对外开放的方法,NodeJs服务器端可以使用第三方jsdom库。