【问题标题】:How do I run lots of regex replacements on all text in html elements using ES6/7?如何使用 ES6/7 对 html 元素中的所有文本运行大量正则表达式替换?
【发布时间】:2017-07-23 05:57:57
【问题描述】:

我正在寻找编写一个客户端脚本,该脚本将使用最奇特和最新的 JavaScript ES6/ES7 方法对页面的文本节点运行多个正则表达式。我该怎么做?

【问题讨论】:

  • @gyre 我正在回答朋友在 Facebook 上提出的一个问题,如果您必须知道的话。他写了这个var elements = document.getElementsByTagName('*'); for (var i = 0; i < elements.length; i++) { var element = elements[i]; for (var j = 0; j < element.childNodes.length; j++) { var node = element.childNodes[j]; if (node.nodeType === 3) { var text = node.nodeValue; var replacedText = text.replace(/Old Text/gi, 'New Text'); if (replacedText !== text) { element.replaceChild(document.createTextNode(replacedText), node); } } } }
  • 只是想向他展示如何改进它,做他想做的事,并使贡献对他人有用。我有很多徽章。谢谢你的问题=)
  • 啊; SO关于自我回答的有趣政策。尽管如此,一个很酷的答案!是的,我想你一定有一些合乎逻辑的动机,因为你已经装饰得很好。

标签: javascript regex ecmascript-6 ecmascript-2016


【解决方案1】:

你可以这样做..jsfiddle

const elements = document.getElementsByTagName('*');
const replaceDict = { 'New Text': /Old Text/gi, 'what': /this/gi };

for ( const e1 of elements ) {
  if (e1.parentNode.nodeName != 'BODY') {
    continue;
  }
  Array
    .from(e1.childNodes)
    .filter( e => e.nodeType === Node.TEXT_NODE )
    .forEach( e2 => {
      let replaceText = e2.nodeValue;
      for ( let [k,v] of Object.entries(replaceDict) ) {
        replaceText = replaceText.replace( v, k );
      }
      if ( replaceText != e2.nodeValue ) {
      	console.log(`Replacing ${e2.nodeValue} with ${replaceText}`);
      	e2.nodeValue = replaceText;
      }
    } )
  ;
}
  <p>
   this is a Old Text test
  </p>
  <p>
   this is a Old Text test Old Text
  </p>

如果愿意,您也可以坚持使用 Array.from() 语法,

const elements = document.getElementsByTagName('*');
const replaceDict = { 'New Text': /Old Text/gi, 'what': /this/gi };

Array.from(elements)
  .filter( e => e.parentNode.nodeName === 'BODY' )
  .forEach( e => {

    Array.from(e.childNodes)
      .filter( e => e.nodeType === Node.TEXT_NODE )
      .forEach( e2 => {
        let replaceText = e2.nodeValue;
        for ( let [k,v] of Object.entries(replaceDict) ) {
          replaceText = replaceText.replace( v, k );
        }
        if ( replaceText != e2.nodeValue ) {
          console.log(`Replacing ${e2.nodeValue} with ${replaceText}`);
          e2.nodeValue = replaceText;
        }
      } );

  } );

这里我们有一个用于编译正则表达式的 replaceDict。我们使用 ES6 迭代器迭代元素,然后将 dom 的 childNodes 转换为 Array 并使用 .filter.forEach 进行替换。无论我们在节点上发出多少不同的替换模式,我们只更新一次文本节点。我们console.log 用于调试目的。

【讨论】:

  • 两点:1)我可以推荐nodeType === Node.TEXT_NODE吗? 3 不是很直观。 2) getElementsByTagName("*") 可以返回任何内容:&lt;style&gt;&lt;script&gt; 包括标签。您可能希望根据用例过滤这些
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-03-16
  • 2013-01-22
  • 1970-01-01
  • 1970-01-01
  • 2011-12-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多