当有多个具有相同“id”的元素时,jQuery如何工作?

时间:2011-12-14 01:34:46

标签: jquery

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

请您解释一下为什么以下3个查询不能得到相同的答案(2)?

Live Demo

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
});

8 个答案:

答案 0 :(得分:80)

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

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

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

但是,您不应该在同一页面上使用相同ID的两个元素。如果您需要CSS,请使用类。


如果您必须通过重复ID进行选择,请使用属性选择器:

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

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

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

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

答案 1 :(得分:5)

应该只有一个元素具有给定的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中看到的内容,它首先检查选择器是否是#a之类的简单ID,如果是,则使用document.getElementById("a")。如果选择器比那个更复杂并且存在querySelectorAll(),则jQuery通常会将选择器传递给内置的浏览器函数,该函数将具有特定于该浏览器的实现。如果querySelectorAll()不存在,那么它将使用Sizzle选择器引擎手动查找将拥有它自己的实现的选择器。因此,根据确切的选择器和浏览器的新增程度,您可以在同一浏览器系列中至少拥有三种不同的实现。然后,各个浏览器都将拥有自己的querySelectorAll()实现。如果您想要可靠地处理这种情况,您可能必须使用您自己的迭代代码,如上所示。

答案 2 :(得分:4)

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;

...同时产生两个结果。

答案 3 :(得分:3)

来自id Selector jQuery page

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

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

答案 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");

答案 5 :(得分:0)

你可以简单地写$('span #a')。length来获得长度。

以下是代码的解决方案:

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

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

答案 6 :(得分:0)

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

$(“ [id = duplicatedId]”)

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

答案 7 :(得分:0)

访问单个项目

<div id='a' data-options='{"url","www.google.com"}'>Google</div>
<div id='a' data-options='{"url","www.facebook.com"}'>Facebook</div>
<div id='a' data-options='{"url","www.twitter.com"}'>Twitter</div>


$( "div[id='a']" ).on('click', function() {
$(location).attr('href', $(this).data('options').url);
});