首页 > 解决方案 > 在javascript中使用replace时属性不应该替换

问题描述

当我用户用另一个内容替换内容时,属性也会替换。表示如果您在下面检查此 URL,则需要将文本“my_text”替换为“Mark”。现在这个替换但包括这个锚属性'my_text'也替换了。所以我只需要替换除属性之外的内容。

var src_str = $("#test").html();
var term = "mY_text";
term = term.replace(/(\s+)/,"(<[^>]+>)*$1(<[^>]+>)*");
var pattern = new RegExp("("+term+")", "gi");

src_str = src_str.replace(pattern, "<mark>$1</mark>");
src_str = src_str.replace(/(<mark>[^<>]*)((<[^>]+>)+)([^<>]*<\/mark>)/,"$1</mark>$2<mark>$4");

$("#test").html(src_str);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="test">this is <a href="mY_text" >my</a> text that needs highlighting my_text</div>

标签: javascriptjquery

解决方案


如果我对您的理解正确,您想在字符串“my_text”出现在文本内容中时替换它,而不是在它出现在属性中时替换它。

这是一个很好的例子,说明为什么用正则表达式操作 HTML 不是一个好主意:正则表达式不知道 DOM 节点、属性和文本之间的区别。相反,使用 DOM 遍历方法来查找要修改的 DOM 部分,并仅处理这些部分:

// contents() includes text nodes, which is what we want to search through here:
$('#test').contents().each(function() {
  // If you were just replacing text, you could simply set this.textContent 
  // to a new value. But since it looks like you're trying to insert 
  // a DOM node, we need to convert the text node into a DOM node:
  if (this.textContent.indexOf('my_text') > -1) { // there's a match 
    var replacementNode = document.createElement('span'); 
    // the regex can be simple here, because we know we're working only with text:
    var newContent = this.textContent.replace(/(my_text)/,'<mark>$1</mark>'); 
    replacementNode.innerHTML = newContent;
    // ... and then replace the text node with the new DOM node:
    this.parentNode.insertBefore(replacementNode,this);
    this.parentNode.removeChild(this)
  };
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="test">this is <a href="my_text" >my</a> text that needs highlighting my_text</div>

(以上只会作用于元素的直接子#test元素。如果您需要在 DOM 树中进行更深入的搜索,可以使用此处显示的方法之一遍历树并找到文本节点,然后应用上面的代码那些元素。)


推荐阅读