【问题标题】:Finding the DOM element with specific text and modify it查找具有特定文本的 DOM 元素并对其进行修改
【发布时间】:2011-09-02 04:33:05
【问题描述】:

我试图弄清楚如何在原始 javascript(没有 jQuery 等)中找到具有特定文本的元素并修改该文本。

我的解决方案的第一个化身......还不够。我所做的基本上是:

var x = document.body.innerHTML;
x.replace(/regular-expression/,"text");
document.body.innerHTML = x;

我天真地以为我成功了,特别是因为它是如此简单。所以我在我的例子中添加了一个图像,并认为我可以每 5 秒检查一次(因为这个字符串可能会动态进入 DOM)......并且图像每 5 秒闪烁一次。

哎呀。

因此,必须有正确的方法来做到这一点。一种专门挑选出特定 DOM 元素并更新该 DOM 元素的文本部分的方法。

现在,总是有“递归搜索孩子,直到找到最深的孩子与字符串”的方法,我想避免。即便如此,我仍然怀疑“将 innerHTML 更改为不同的东西”是否是更新 DOM 元素的正确方法。

那么,在 DOM 中搜索字符串的正确方法是什么?更新 DOM 元素文本的正确方法是什么?

【问题讨论】:

  • 在使用 document.evaluate 和 XPath 的有趣解决方案中,但不幸的是,这在 IE 中不起作用,我认为它没有实际意义:jsfiddle.net/GRmF5/6。还有一个实用函数使用textContent / innerText 而不是innerHTML

标签: javascript string search dom text


【解决方案1】:
x.replace(/regular-expression/,"text");

会返回一个值所以

var y = x.replace(/regular-expression/,"text");

现在您可以分配新值了。

document.body.innerHTML = y;

但是你要考虑一下,你不想为了改变一小段代码而得到整个body,为什么不获取div或任何元素的内容等等

示例:

<p id='paragraph'>
    ... some text here ...
</p>

现在你可以使用javascript了

var para = document.getElementById('paragraph').innerHTML;
var newPara = para.replace(/regex/,'new content');

para.innerHTML = newPara;

这应该是最简单的方法了。

【讨论】:

  • 很简单,直到他们想要寻找任何会破坏序列化 HTML 的东西,这是一个非常现实的可能性。
  • 是的,我想当您正在寻找复杂的模式时,我想这不是那么简单
  • 我不能依赖它在任何特定的地方。我需要它的多功能性和动态性,因为它需要在任何人的网页上工作。
【解决方案2】:

忘记正则表达式。

遍历每个文本节点(递归执行将是最优雅的)并在找到文本时修改文本节点。如果只是查找字符串,可以使用indexOf()

【讨论】:

  • 如何遍历每个文本节点?我以前从未这样做过。
  • @rk1s This article 似乎成功了。
  • 我认为那篇文章确实做到了。谢谢 :) 现在就试试看
  • 搜索不必是递归的,它可以迭代 getElementsByTagName 返回的 NodeList。
  • @RobG 当然。但我从来没有说过它必须
【解决方案3】:

不要将innerHTML 与正则表达式一起使用,对于非平凡的内容,它几乎肯定会失败。此外,浏览器从实时 DOM 生成它的方式仍然存在差异。替换 innerHTML 还将删除作为元素属性添加的任何事件侦听器(即像element.onclick = fn)。

如果您可以将字符串包含在具有您可以搜索的属性或属性(id、类等)的元素中,则最好,但如果不这样做,则搜索文本节点是最好的方法。

编辑

尝试对 HTML 文档使用通用文本选择功能可能会导致非常复杂的算法,因为字符串可能是复杂结构的一部分,例如:

<h1>Some <span class="foo"><em>s</em>pecial</span> heading</h1>

搜索字符串“特殊标题”很棘手,因为它分为 2 个元素。包装另一个元素(比如突出显示)也不是微不足道的,因为生成的 DOM 结构必须是有效的。例如,上面匹配“some special”的文本可以用span包裹,但不能用div包裹。

任何此类功能都必须附有说明其限制和最适当用途的文档。

【讨论】:

  • 不能依赖它在一个封闭的元素中。我需要它非常通用,因为我希望人们能够将此代码粘贴在任何页面上。这不是为我准备的,而是为我们的最终客户准备的。
  • +1 用于丢失提及事件侦听器。 innerHTML 最常见的被忽略的副作用。
  • +1 那么附加addEventListener()attachEvent()的事件处理程序在序列化HTML然后重置它时仍然可以工作吗?从来不知道……我一直以为它们都会坏掉。
【解决方案4】:

编辑:根据 RobG 的建议将 querySelectorAll 更改为 getElementsByTagName。

您可以使用 getElementsByTagName 函数来获取页面上的所有标签。从那里,您可以检查他们的孩子,看看他们是否有任何文本节点作为孩子。如果他们这样做,那么您将查看他们的文本,看看它是否符合您的需要。这是一个示例,它将使用控制台对象打印出文档中每个文本节点的文本:

var elms = document.getElementsByTagName("*"),
    len = elms.length;
for(var ii = 0; ii < len; ii++) {
    var myChildred = elms[ii].childNodes;
    len2 = myChildred.length;
    for (var jj = 0; jj < len2; jj++) {
        if(myChildred[jj].nodeType === 3) {
            console.log(myChildred[jj].nodeValue);

            // example on update a text node's value
            myChildred[jj].nodeValue = myChildred[jj].nodeValue.replace(/test/,"123");
        }
    }
}

要更新 DOM 元素的文本,只需更新文本节点的 nodeValue 属性即可。

【讨论】:

  • 不需要使用 qSA,它仅在最近的浏览器中可用。 getElementsByTagName('*') 会做同样的事情(或多或少,它返回一个活动列表而不是静态列表,但相同的元素在两个列表中以相同的顺序排列)并且被使用的每个浏览器支持。
  • 很好,RobG,你是对的。在这种情况下,这是一个比 querySelectorAll 更好的选择。
【解决方案5】:

现在,总是有“递归搜索孩子,直到找到最深的孩子与字符串”的方法,我想避免。

我想在一个无序随机列表中搜索一个元素。现在,我想避免“遍历所有元素,直到找到所需的方法”。

老式磁带,录音,聆听,冥想。

顺便说一句,请参阅:James Padolsey 的 github上的 Find and replace text with JavaScript
(也是高博articlesexplaining吧)

【讨论】:

猜你喜欢
  • 2017-08-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-13
  • 1970-01-01
  • 2014-03-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多