【问题标题】:How does jQuery work when there are multiple elements with the same ID value?当有多个具有相同 ID 值的元素时,jQuery 是如何工作的?
【发布时间】:2012-01-19 21:06:01
【问题描述】:

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

【问题讨论】:

    标签: html jquery identifier


    【解决方案1】:

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

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

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

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


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

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

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

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

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

    【讨论】:

    • 您能解释一下注意吗?什么时候添加标签选择器有帮助?
    • @Misha Moroshko - 只要有可能,您应该包含一个标签选择器。这样做的原因是标签选择器比属性选择器效率。如果您使用标签选择器限定属性选择器,jQuery 将首先使用标签选择器查找带有该标签的元素,然后仅在这些元素上运行属性选择器。这样效率更高。
    • 我在这里看到div#some_id#some_id 慢:stackoverflow.com/q/7262116/247243
    • @Misha Moroshko - 这是因为 ID 选择器比标签选择器更有效。但是标签选择器仍然比属性选择器快。
    • 对于它的价值,ASP.NET Razor 语法会自动为单选按钮之类的东西添加重复的 id,因此我在这里!
    【解决方案2】:

    应该只有一个元素具有给定的 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 的方法,如果你坚持使用它的话。
    【解决方案3】:

    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 这个例子展示了如何访问元素
    【解决方案4】:

    来自id Selector jQuery page

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

    淘气的谷歌。但他们甚至没有关闭他们的&lt;html&gt;&lt;body&gt; 我听到的标签。但问题是,为什么 Misha 的第二个和第三个查询返回 2 而不是 1。

    【讨论】:

    • 这并没有回答为什么使用组合选择器返回多个元素的问题。
    【解决方案5】:

    如果您有多个具有相同 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");
    

    【讨论】:

    • 这并没有回答为什么使用组合选择器返回多个元素的问题。
    【解决方案6】:

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

    $("[id=duplicatedId]")
    

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

    【讨论】:

    • 这并没有回答为什么使用组合选择器返回多个元素的问题。
    【解决方案7】:

    访问单个项目

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

    【讨论】:

      【解决方案8】:

      您可以简单地编写 $('span#a').length 来获取长度。

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

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

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

      【讨论】:

      • 这并没有回答为什么使用组合选择器返回多个元素的问题。
      猜你喜欢
      • 2017-06-09
      • 2020-05-24
      • 1970-01-01
      • 1970-01-01
      • 2011-02-27
      • 2019-06-16
      • 1970-01-01
      • 2011-04-06
      相关资源
      最近更新 更多