我想获得一个元素的所有后代文本节点,作为一个 jQuery 集合。最好的方法是什么?
如何使用 jQuery 选择文本节点?
IT技术
javascript
jquery
dom
                    2021-01-12 20:28:36
                
                    
                
            
        6个回答
            jQuery 没有一个方便的功能。您需要组合contents(),它只提供子节点但包括文本节点,与find(),它提供所有后代元素但不提供文本节点。这是我想出的:
var getTextNodesIn = function(el) {
    return $(el).find(":not(iframe)").addBack().contents().filter(function() {
        return this.nodeType == 3;
    });
};
getTextNodesIn(el);
注意:如果您使用的是 jQuery 1.7 或更早版本,则上面的代码将不起作用。要解决此问题,请替换addBack()为andSelf(). 从 1.8 开始andSelf()不推荐使用addBack()。
与纯 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);
Jauco 在评论中发布了一个很好的解决方案,所以我在这里复制它:
$(elem)
  .contents()
  .filter(function() {
    return this.nodeType === 3; //Node.TEXT_NODE
  });
$('body').find('*').contents().filter(function () { return this.nodeType === 3; });
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);
  });
});
div { margin-left: 1em; }
<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>
我使用接受的过滤器功能得到了很多空文本节点。如果您只对选择包含非空格的文本节点感兴趣,请尝试向nodeValue您的filter函数添加条件,例如简单的$.trim(this.nodevalue) !== '':
$('element')
    .contents()
    .filter(function(){
        return this.nodeType === 3 && $.trim(this.nodeValue) !== '';
    });
或者为了避免内容看起来像空格但不是(例如软连­字符、换行符\n、制表符等)的奇怪情况,您可以尝试使用正则表达式。例如,\S将匹配任何非空白字符:
$('element')
        .contents()
        .filter(function(){
            return this.nodeType === 3 && /\S/.test(this.nodeValue);
        });
其它你可能感兴趣的问题