如何使用jQuery选择文本节点?

Chr*_*ard 380 javascript jquery dom

我想得到一个元素的所有后代文本节点,作为jQuery集合.最好的方法是什么?

Tim*_*own 255

jQuery没有这方面的便利功能.您需要组合contents(),它将只提供子节点但包含文本节点find(),它提供所有后代元素但不提供文本节点.这是我想出的:

var getTextNodesIn = function(el) {
    return $(el).find(":not(iframe)").addBack().contents().filter(function() {
        return this.nodeType == 3;
    });
};

getTextNodesIn(el);
Run Code Online (Sandbox Code Playgroud)

注意:如果您使用的是jQuery 1.7或更早版本,则上述代码将无效.为了解决这个问题,更换addBack()andSelf().andSelf()不赞成addBack()从1.8开始.

与纯DOM方法相比,这有点低效,并且必须包含一个丑陋的解决方法,用于jQuery的contents()函数重载(感谢注释中的@rabidsnail指出这一点),所以这里是使用简单递归函数的非jQuery解决方案.该includeWhitespaceNodes参数控制是否在输出中包含空白文本节点(在jQuery中它们被自动过滤掉).

更新:修复includeWhitespaceNodes为假时的错误.

function getTextNodesIn(node, includeWhitespaceNodes) {
    var textNodes = [], nonWhitespaceMatcher = /\S/;

    function getTextNodes(node) {
        if (node.nodeType == 3) {
            if (includeWhitespaceNodes || nonWhitespaceMatcher.test(node.nodeValue)) {
                textNodes.push(node);
            }
        } else {
            for (var i = 0, len = node.childNodes.length; i < len; ++i) {
                getTextNodes(node.childNodes[i]);
            }
        }
    }

    getTextNodes(node);
    return textNodes;
}

getTextNodesIn(el);
Run Code Online (Sandbox Code Playgroud)


Chr*_*ard 207

Jauco在评论中发布了一个很好的解决方案,所以我在这里复制它:

$(elem)
  .contents()
  .filter(function() {
    return this.nodeType === 3; //Node.TEXT_NODE
  });
Run Code Online (Sandbox Code Playgroud)

  • IE7没有定义Node全局,所以你不得不使用this.nodeType == 3,不幸的是:http://stackoverflow.com/questions/1423599/node-textnode-and-ie7 (37认同)
  • 实际上是$(elem).contents().filter(function(){return this.nodeType == Node.TEXT_NODE;}); 足够 (34认同)
  • 这是否不仅返回作为元素的直接子节点的文本节点而不是OP请求的元素的后代? (16认同)
  • 当文本节点深度嵌套在其他元素中时,这将不起作用,因为contents()方法仅返回直接子节点,https://api.jquery.com/contents/ (6认同)
  • 在IE7下不起作用.节点未定义. (5认同)
  • @Jauco,不,还不够!as .contents() 仅返回直接子节点 (2认同)

He *_*rik 16

$('body').find('*').contents().filter(function () { return this.nodeType === 3; });
Run Code Online (Sandbox Code Playgroud)


Sal*_*n A 6

jQuery.contents()可用于jQuery.filter查找所有子文本节点.稍微扭曲一下,您也可以找到孙子文本节点.不需要递归:

$(function() {
  var $textNodes = $("#test, #test *").contents().filter(function() {
    return this.nodeType === Node.TEXT_NODE;
  });
  /*
   * for testing
   */
  $textNodes.each(function() {
    console.log(this);
  });
});
Run Code Online (Sandbox Code Playgroud)
div { margin-left: 1em; }
Run Code Online (Sandbox Code Playgroud)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

<div id="test">
  child text 1<br>
  child text 2
  <div>
    grandchild text 1
    <div>grand-grandchild text 1</div>
    grandchild text 2
  </div>
  child text 3<br>
  child text 4
</div>
Run Code Online (Sandbox Code Playgroud)

的jsfiddle