当多个具有相同ID值的元素时,jQuery如何工作?


74

我从Google的AdWords网站获取数据,该网站包含多个具有相同元素的元素id

您能否解释为什么以下3个查询没有得到相同答案(2)?

现场演示

HTML:

<div>
    <span id="a">1</span>
    <span id="a">2</span>
    <span>3</span>
</div>

JS:

$(function() {
    var w = $("div");
    console.log($("#a").length);            // 1 - Why?
    console.log($("body #a").length);       // 2
    console.log($("#a", w).length);         // 2
});

Answers:


104

根据W3C规范,具有2个具有相同ID的元素不是有效的html。

当您的CSS选择器只有一个ID选择器(并且未在特定上下文中使用)时,jQuery使用本机document.getElementById方法,该方法仅返回具有该ID的第一个元素。

但是,在其他两个实例中,jQuery依赖于Sizzle选择器引擎(或者querySelectorAll,如果可用),该引擎显然选择了两个元素。结果可能因浏览器而异。

但是,在同一页面上绝对不能有两个具有相同ID的元素。如果您的CSS需要它,请改用一个类。


如果绝对必须通过重复的ID选择,请使用属性选择器:

$('[id="a"]');

看看小提琴:http : //jsfiddle.net/P2j3f/2/

注意:如果可能,您应该使用标签选择器来限定该选择器,如下所示:

$('span[id="a"]');

2
你能解释一下注释吗?什么时候添加标签选择器有帮助?
Misha Moroshko '12

5
@Misha Moroshko-只要有可能,就应包括标签选择器。这样做的原因是因为标签选择器是比属性选择更为有效。如果使用标签选择器来限定属性选择器,则jQuery将首先使用标签选择器来查找具有该标签的元素,然后仅对那些元素运行属性选择器。这实际上更加有效。
约瑟夫·西尔伯

2
我在这里看到div#some_id的速度比#some_idstackoverflow.com/q/7262116/247243
Misha Moroshko 2011年

4
@Misha Moroshko-这是因为ID选择器比标记选择器更有效。但是标签选择器仍然比属性选择器快。
约瑟夫·席尔伯

对于它的价值,ASP.NET Razor语法会自动为单选按钮之类的内容添加重复的ID,因此为什么我在这里!
加雷斯(Gareth)

6

只能有一个具有给定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
});

如果由于无法修复文档而要可靠地查看具有相同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);
}

或者,使用jQuery:

$("div *").filter(function() {return(this.id == "a");});

jQuery工作示例:http : //jsfiddle.net/jfriend00/XY2tX/

至于为什么得到不同的结果,这与执行实际选择器操作的任何代码的内部实现有关。在jQuery中,您可以研究代码以找出给定版本在做什么,但是由于这是非法的HTML,因此无法保证它会随着时间的推移保持不变。根据我在jQuery中看到的内容,它首先检查选择器是否是一个简单的id #a,如果是,则使用它document.getElementById("a")。如果选择器比它更复杂并且querySelectorAll()存在,jQuery将经常将选择器传递给内置的浏览器功能,该功能具有特定于该浏览器的实现。如果querySelectorAll()不存在,则它将使用Sizzle选择器引擎手动找到具有自己实现的选择器。因此,您可以在同一浏览器系列中至少拥有三种不同的实现方式,具体取决于确切的选择器和浏览器的新颖程度。然后,各个浏览器将具有各自的querySelectorAll()实现。如果您想可靠地处理这种情况,则可能必须使用您自己的迭代代码,如上文所述。


他不能。他是从Google那里得到的,这就是问题
拉尔夫·拉维尔

@RalphLavelle-如果您坚持使用它,我添加了一种处理dup ID的方法。
jfriend00 2011年

5

jQuery的id选择器仅返回一个结果。第二和第三条语句中的descendantmultiple选择器旨在选择多个元素。它类似于:

陈述1

var length = document.getElementById('a').length;

...产生一个结果。

陈述2

var length = 0;
for (i=0; i<document.body.childNodes.length; i++) {
    if (document.body.childNodes.item(i).id == 'a') {
        length++;
    }
}

...产生两个结果。

声明3

var length = document.getElementById('a').length + document.getElementsByTagName('div').length;

...也产生两个结果。


您可以尝试使用此选项jsfiddle.net/sx7jnh58/1该示例显示了如何访问元素
Pankaj Shinde

2

id Selector jQuery页面

每个id值在文档中只能使用一次。如果为多个元素分配了相同的ID,则使用该ID的查询将仅选择DOM中的第一个匹配元素。但是,不应依赖这种行为。包含多个使用相同ID的元素的文档无效。

顽皮的Google。但是他们甚至都没有关闭我听到的<html><body>标签。问题是,为什么Misha的第二和第三查询返回2而不是1。


这不能回答有关为什么使用组合选择器返回多个元素的问题。
isherwood'4

2

如果您有多个具有相同ID或相同名称的元素,只需将相同的类分配给这些多个元素并通过索引访问它们并执行所需的操作即可。

  <div>
        <span id="a" class="demo">1</span>
        <span id="a" class="demo">2</span>
        <span>3</span>
    </div>

JQ:

$($(".demo")[0]).val("First span");
$($(".demo")[1]).val("Second span");

这不能回答有关为什么使用组合选择器返回多个元素的问题。
isherwood'4

0

每个人都说“每个id值在一个文档中只能使用一次”,但是当我们有一个愚蠢的页面包含多个具有相同id的元素时,我们将如何获取所需的元素。如果使用JQuery'#duplicatedId'选择器,则仅获得第一个元素。要选择其他元素,您可以执行以下操作

$(“ [id = duplicatedId]”)

您将获得一个所有元素都为id = duplicatedId的集合


这不能回答有关为什么使用组合选择器返回多个元素的问题。
isherwood'4

-1

您只需编写$('span#a')。length即可获取长度。

这是您的代码的解决方案:

console.log($('span#a').length);

尝试JSfiddle:https ://jsfiddle.net/vickyfor2007/wcc0ab5g/2/


这不能回答有关为什么使用组合选择器返回多个元素的问题。
isherwood'4
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.