检索文本节点

时间:2016-01-04 14:30:31

标签: jquery

想要使用一些“可读”的元素从元素中获取文本节点。方法,我来到这个奇怪的行为,我无法解释。

-jsFiddle-

使用以下HTML标记:

<div>text node <b>and b element</b></div>

文本节点不是DOM元素,所以我想知道这是否有效:

var textnode = $('div').contents().filter(':not(*)'); //returns jq empty set

即使使用.filter('*')并且没有返回文本节点但其他元素(b)也失败。

所以测试它,我使用not()方法,我不确定它是否适用于文本节点:

var textnode = $('div').contents().not('*'); //returns jq empty set

我们承认。 这个返回文本节点:

var textnode = $('div').contents().not(':not(:not(*))'); //returns text node in set

为什么 .not('*').not(':not(:not(*))')工作时失败? 我无法解释。

PS: .filter(':not(:not(:not(*)))')失败,而我期望它与.not(':not(:not(*))')完全一样

1 个答案:

答案 0 :(得分:3)

因为.not(':not(:not(*))')不是一个简单的选择器(基本上,它有多个“部分”),所以它的处理方式不同。

简单选择器(如.filter(':not(*)').not('*'))通过名为jQuery.filter()的布尔指示符传递给not函数。 此指标在:not(...)的选择器周围包含额外的.not(selector)

jQuery.filter()返回通过选择器进行过滤的节点。它有一个额外的检查,所以它只返回nodeType 1(元素)的节点。

对于复杂的选择器(如.not(':not(:not(*))')),该机制的工作方式略有不同;选择器传递给jQuery.filter(),但未设置not布尔指示符。 相反,从jQuery.filter()返回的节点将与原始节点列表进行比较,并根据您使用.not()还是.filter()进行过滤或调出。 由于jQuery.filter()只返回元素,因此与原始节点列表进行比较时,找不到文本元素的任何匹配项。 对于.not(':not(:not(*))'),这意味着根据此逻辑,不应过滤掉文本节点,因为它不在jQuery.filter()返回的要过滤的节点列表中。

这些不同机制的原因可能是你不能只在任何复杂的选择器周围包裹:not(...);它可能会改变预期的含义。

尽管他们确实在.contents() documentation中声明大多数jQuery都不支持文本节点。 它可以通过明确地仅从winnow函数返回nodeType 1节点来解决。

原始jQuery 1.11.3代码:

function winnow( elements, qualifier, not ) {
    //...

    return jQuery.grep( elements, function( elem ) {
        return ( jQuery.inArray( elem, qualifier ) >= 0 ) !== not;
    });
}

更改了代码:

function winnow( elements, qualifier, not ) {
    //...

    return jQuery.grep( elements, function( elem ) {
        return ( jQuery.inArray( elem, qualifier ) >= 0 ) !== not && elem.nodeType === 1;
    });
}

我不知道这是否属于错误,但它至少是jQuery中可解决的不一致。您可能希望将其报告给jQuery。