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

新手上路,请多包涵

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

您能否解释一下为什么以下 3 个查询不会产生相同的答案 (2)?

现场演示

HTML:

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

记者:

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

原文由 Misha Moroshko 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.1k
2 个回答

根据 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"]');

这是因为类型选择器比属性选择器更有效。如果用类型选择器限定属性选择器,jQuery 将首先使用类型选择器查找该类型的元素,然后仅在这些元素上运行属性选择器。这样效率更高。

原文由 Joseph Silber 发布,翻译遵循 CC BY-SA 4.0 许可协议

应该只有一个元素具有给定的 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() 实现。如果你想可靠地处理这种情况,你可能必须使用你自己的迭代代码,正如我在上面说明的那样。

原文由 jfriend00 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题