想要使用一些“可读”的元素从元素中获取文本节点。方法,我来到这个奇怪的行为,我无法解释。
使用以下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(*))')
完全一样
答案 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。