Javascript .replace 命令替换页面文本?

IT技术 javascript
2021-01-15 12:37:47

JavaScript 命令 .replace 可以替换任何网页中的文本吗?我想创建一个 Chrome 扩展程序来替换任何网页中的特定单词以说其他内容(例如蛋糕而不是馅饼)。

3个回答

.replace方法是一个字符串操作,因此在由 DOM Node 对象组成的 HTML 文档上运行该操作并不简单。

使用 TreeWalker API

遍历 DOM 中的每个节点并替换其中的文本的最佳方法是使用document.createTreeWalker方法创建一个 TreeWalker 对象。这是在许多 Chrome 扩展程序中使用的做法!

// create a TreeWalker of all text nodes
var allTextNodes = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT),
    // some temp references for performance
    tmptxt,
    tmpnode,
    // compile the RE and cache the replace string, for performance
    cakeRE = /cake/g,
    replaceValue = "pie";

// iterate through all text nodes
while (allTextNodes.nextNode()) {
    tmpnode = allTextNodes.currentNode;
    tmptxt = tmpnode.nodeValue;
    tmpnode.nodeValue = tmptxt.replace(cakeRE, replaceValue);
}

与另一元件替换部分文本或以文本的中间添加的元素,使用DOM splitTextcreateElementinsertBefore方法,例如

不要使用innerHTML 或innerText 或jQuery .html()

// the innerHTML property of any DOM node is a string
document.body.innerHTML = document.body.innerHTML.replace(/cake/g,'pie')
  • 它通常较慢(尤其是在移动设备上)。
  • 它有效地删除并替换了整个 DOM,这并不好,并且可能会产生一些副作用:它会破坏 JavaScript 代码中附加的所有事件侦听器(通过 addEventListener 或 .onxxxx 属性),从而部分/完全破坏功能。
  • 然而,这是一种常见、快速且非常脏的方法。
@zetlen 非常感谢,我创建了一个新问题stackoverflow.com/questions/13458291 /... 因为我发现您的解决方案createTreeWalker()无法与 Internet Explorer 一起使用...
2021-04-01 12:37:47
感谢这些信息,我的解决方案确实很脏
2021-04-07 12:37:47
@zetlen 请如何替换,cakeRE = 'keyword' by replaceValue = '<a herf=\"#\">keyword</a>';因为它只显示 html 代码而不执行它?
2021-04-08 12:37:47
@Valky 那是因为您正在更改文本节点的字符串值,并且根据定义,文本节点不包含 HTML。您可以使用节点的parentNode属性在它自己和它的父节点之间插入一个锚标记。请将此作为单独的问题提出!
2021-04-10 12:37:47
+1 为createTreeWalker我不知道该功能存在。这很酷。
2021-04-12 12:37:47

好的,所以 createTreeWalker 方法是执行此操作的正确方法,并且是一种好方法。不幸的是,我需要这样做来支持不支持 document.createTreeWalker 的 IE8。悲伤的伊恩很伤心。

如果你想像顽皮的孩子一样使用非标准的innerHTML调用在页面文本上使用.replace来做到这一点,你需要小心,因为它会替换标签内的文本,导致XSS漏洞和页面的全面破坏.

您需要做的只是替换标签的文本 OUTSIDE ,我与之匹配:

var search_re = new RegExp("(?:>[^<]*)(" + stringToReplace + ")(?:[^>]*<)", "gi");

很恶心,不是吗。您可能希望通过替换一些结果,然后将其余结果保留在setTimeout调用中来缓解任何缓慢,如下所示:

// replace some chunk of stuff, the first section of your page works nicely
// if you happen to have that organization
//
setTimeout(function() { /* replace the rest */ }, 10);

它将在替换第一个块后立即返回,让您的页面继续快乐的生活。对于您的替换调用,您还需要替换临时字符串中的大块

var tmp = element.innerHTML.replace(search_re, whatever); 
/* more replace calls, maybe this is in a for loop, i don't know what you're doing */  
element.innerHTML = tmp;

以尽量减少回流(当页面重新计算定位并重新渲染所有内容时)。对于大页面,除非您小心,否则这可能会很慢,因此优化指针。再一次,除非您绝对需要,否则不要这样做。使用 zetlen 在上面发布的 createTreeWalker 方法。

你有没有尝试过这样的事情?

$('body').html($('body').html().replace('pie','cake'));