我从Google的AdWords网站上获取数据,该网站包含多个相同的元素id.
你能否解释为什么以下3个查询不能得到相同的答案(2)?
HTML:
<div>
<span id="a">1</span>
<span id="a">2</span>
<span>3</span>
</div>
Run Code Online (Sandbox Code Playgroud)
JS:
$(function() {
var w = $("div");
console.log($("#a").length); // 1 - Why?
console.log($("body #a").length); // 2
console.log($("#a", w).length); // 2
});
Run Code Online (Sandbox Code Playgroud)
Jos*_*ber 91
根据W3C规范,具有相同ID的2个元素不是有效的html.
当您的CSS选择器只有一个ID选择器(并且未在特定上下文中使用)时,jQuery使用本机document.getElementById方法,该方法仅返回具有该ID的第一个元素.
但是,在另外两个实例中,jQuery依赖于Sizzle选择器引擎(或者querySelectorAll,如果可用的话),它显然选择了两个元素.结果可能因浏览器而异.
但是,您不应该在同一页面上具有相同ID的两个元素.如果您需要CSS,请使用类.
如果您绝对必须通过重复ID进行选择,请使用属性选择器:
$('[id="a"]');
Run Code Online (Sandbox Code Playgroud)
看看小提琴:http://jsfiddle.net/P2j3f/2/
注意:如果可能,您应该使用标记选择器限定该选择器,如下所示:
$('span[id="a"]');
Run Code Online (Sandbox Code Playgroud)
应该只有一个具有给定id的元素.如果您遇到这种情况,请参阅我的答案选项的下半部分.
当具有相同id(非法HTML)的多个元素时,浏览器的行为方式不是由规范定义的.您可以测试所有浏览器并了解它们的行为方式,但使用此配置或依赖任何特定行为是不明智的.
如果希望多个对象具有相同的标识符,请使用类.
<div>
<span class="a">1</span>
<span class="a">2</span>
<span>3</span>
</div>
$(function() {
var w = $("div");
console.log($(".a").length); // 2
console.log($("body .a").length); // 2
console.log($(".a", w).length); // 2
});
Run Code Online (Sandbox Code Playgroud)
如果您想要可靠地查看具有相同ID的元素,因为您无法修复文档,那么您将不得不进行自己的迭代,因为您不能依赖任何内置的DOM函数.
你可以这样做:
function findMultiID(id) {
var results = [];
var children = $("div").get(0).children;
for (var i = 0; i < children.length; i++) {
if (children[i].id == id) {
results.push(children[i]);
}
}
return(results);
}
Run Code Online (Sandbox Code Playgroud)
或者,使用jQuery:
$("div *").filter(function() {return(this.id == "a");});
Run Code Online (Sandbox Code Playgroud)
jQuery工作示例:http://jsfiddle.net/jfriend00/XY2tX/.
至于为什么你会得到不同的结果,这与任何代码片段的内部实现有关,就是执行实际的选择器操作.在jQuery中,您可以研究代码以找出任何给定版本正在执行的操作,但由于这是非法的HTML,因此不能保证它会随着时间的推移保持不变.从我在jQuery中看到的,它首先检查选择器是否是一个简单的id #a,如果是,只是使用document.getElementById("a").如果选择器比那个更复杂并且querySelectorAll()存在,jQuery通常会将选择器传递给内置的浏览器函数,该函数将具有特定于该浏览器的实现.如果querySelectorAll()不存在,那么它将使用Sizzle选择器引擎手动查找将拥有它自己的实现的选择器.因此,根据确切的选择器和浏览器的新增程度,您可以在同一浏览器系列中至少拥有三种不同的实现.然后,各个浏览器都将拥有自己的querySelectorAll()实现.如果您想要可靠地处理这种情况,您可能必须使用自己的迭代代码,如上所述.
jQuery 的id选择器只返回一个结果。第二条和第三条语句中的descendantandmultiple选择器旨在选择多个元素。它类似于:
声明 1
var length = document.getElementById('a').length;
Run Code Online (Sandbox Code Playgroud)
...产生一个结果。
声明 2
var length = 0;
for (i=0; i<document.body.childNodes.length; i++) {
if (document.body.childNodes.item(i).id == 'a') {
length++;
}
}
Run Code Online (Sandbox Code Playgroud)
...产生两个结果。
声明 3
var length = document.getElementById('a').length + document.getElementsByTagName('div').length;
Run Code Online (Sandbox Code Playgroud)
...也产生两个结果。