jQuery InnerText 不包括子元素。

5

我在想如何获取嵌套列表项的文本,而不包括其子项的文本。

<ul>
   <li id="node">
      I want this
    <ul>
       <li>
          I don't want this
        </li>
    </ul>
    </li>
</ul>

现在使用jQuery和$('#node').text()会获取到所有的文本,但我只想要"I want this"这个字符串。

4个回答

10

Tim的解决方案可行。如果您的标记始终以该格式固定,并且您只需要读取该第一段文本直到子元素,那么您甚至可以仅使用以下内容:

node.firstChild.data

1
我本来会建议使用 nodeValue(从未见过 data)。对于其他人想知道它们之间的区别:http://www.mail-archive.com/svg-developers@yahoogroups.com/msg06963.html 在这个上下文中,它们是等价的。 - Crescent Fresh

5
以下代码可以获取一个节点直接子节点中所有文本节点的拼接字符串:
function getChildText(node) {
  var text = "";
  for (var child = node.firstChild; !!child; child = child.nextSibling) {
    if (child.nodeType === 3) {
      text += child.nodeValue;
    }
  }
  return text;
}

alert( getChildText(document.getElementById("node")) );

你可能还想在文本块之间插入一个空格。 - Neall
这是一个很好的答案,只是可能有一个小调整可以使一些人受益:如果你返回一个字符串数组,那么你会得到两个好处:首先,你可以避免潜在的昂贵的字符串连接操作;其次,调用者可以通过自己调用“join”方法来选择分隔符。 - OlduwanSteve
1
@OlduwanSteve:没错,虽然我认为在现代浏览器中,字符串拼接并不比调用join方法更耗费资源。无论如何,这很容易进行微调;总体的方法是最重要的。 - Tim Down
每一天都是一个学校的日子! - OlduwanSteve

4
这个例子使用.contents()获取所有子节点(包括文本节点),然后使用.map()根据nodeType将每个子节点转换为字符串。如果节点是文本节点(即不在<li>中的文本),则返回其nodeValue

这将返回一个包含字符串的jQuery集合,因此我们调用.get()来获取一个“标准”的数组对象,我们可以在其上调用.join()
// our 'div' that contains your code:
var $html = $('<li id="node">I want this<ul><li>I dont want this</li></ul>    </li>');

// Map the contents() into strings
$html.contents().map(function() { 
  // if the node is a textNode, use its nodeValue, otherwise empty string
  return this.nodeType == 3 ? this.nodeValue : undefined; 
  // get the array, and join it together:
}).get().join('');

// "I want this    " -- note the extra whitespace from after the <ul>

为了使调用更简单:

$.fn.directText=function(delim) {
  if (!delim) delim = '';
  return this.contents().map(function() { return this.nodeType == 3 ? this.nodeValue : undefined}).get().join(delim);
};

$html.directText();
// "I want this    "

或者稍微更健壮一些的版本,允许修剪空格/更改连接字符串:

$.fn.directText = function(settings) {
   settings = $.extend({},$.fn.directText.defaults, settings);
   return this.contents().map(function() {
     if (this.nodeType != 3) return undefined; // remove non-text nodes
     var value = this.nodeValue;
     if (settings.trim) value = $.trim(value);
     if (!value.length) return undefined; // remove zero-length text nodes
     return value;
   }).get().join(settings.joinText);
};

$.fn.directText.defaults = {
   trim: true,
   joinText: ''
};

0

如果这是您经常需要做的事情,有一个Text Children Plugin可以解决。它还提供了几种输出选项。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接