Как работает jQuery, когда есть несколько элементов с одинаковым идентификатором? - PullRequest
64 голосов
/ 14 декабря 2011

Я получаю данные с веб-сайта 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
});

Ответы [ 7 ]

82 голосов
/ 14 декабря 2011

Наличие 2 элементов с одинаковым идентификатором недопустимо в формате html согласно спецификации W3C.

Когда ваш селектор CSS имеет только селектор идентификатора (и не используется в определенном контексте), jQuery использует собственный метод document.getElementById, который возвращает только первый элемент с этим идентификатором.

Однако в двух других случаях jQuery использует механизм выбора Sizzle (или querySelectorAll, если доступен), который, очевидно, выбирает оба элемента. Результаты могут отличаться в зависимости от браузера.

Однако на одной странице никогда не должно быть двух элементов с одинаковым идентификатором. Если вам это нужно для CSS, используйте вместо этого класс.


Если вам абсолютно необходимо выбрать по дублированному идентификатору, используйте селектор атрибута:

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

Взгляните на скрипку: http://jsfiddle.net/P2j3f/2/

Примечание: если возможно, вы должны квалифицировать этот селектор с помощью селектора тегов, например так:

$('span[id="a"]');
5 голосов
/ 14 декабря 2011

Должен быть только один элемент с заданным идентификатором. Если вы застряли в такой ситуации, посмотрите варианты ответа во второй половине моего ответа.

Как ведет себя браузер, когда у вас есть несколько элементов с одинаковым идентификатором (недопустимый 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
});

Если вы хотите надежно смотреть на элементы с одинаковыми идентификаторами, потому что вы не можете исправить документ, то вам придется сделать свою собственную итерацию, поскольку вы не можете полагаться ни на одну из встроенных функций 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, и, если это так, просто используется document.getElementById("a"). Если селектор более сложен, чем этот, и querySelectorAll() существует, jQuery часто передает селектор встроенной функции браузера, которая будет иметь реализацию, специфичную для этого браузера. Если querySelectorAll() не существует, он будет использовать механизм выбора Sizzle для ручного поиска переключателя, который будет иметь свою собственную реализацию. Таким образом, вы можете иметь как минимум три разных реализации в одном семействе браузеров, в зависимости от точного селектора и того, насколько новый браузер. Тогда отдельные браузеры будут иметь свои собственные реализации querySelectorAll(). Если вы хотите надежно справиться с этой ситуацией, вам, вероятно, придется использовать свой собственный итерационный код, как показано выше.

4 голосов
/ 14 декабря 2011
Селектор

jQuery id возвращает только один результат. Селекторы descendant и multiple во втором и третьем операторах предназначены для выбора нескольких элементов. Это похоже на:

Заявление 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 голосов
/ 14 декабря 2011

Со страницы jQuery селектора идентификаторов :

Каждое значение идентификатора должно использоваться только один раз в документе.Если более чем одному элементу был присвоен один и тот же идентификатор, запросы, использующие этот идентификатор, будут выбирать только первый соответствующий элемент в DOM.Однако на такое поведение нельзя полагаться;недопустимый документ с более чем одним элементом, использующим один и тот же идентификатор.

Непослушный Google.Но они даже не закрывают свои теги <html> и <body>, которые я слышу.Вопрос в том, почему второй и третий запросы Миши возвращают 2, а не 1.

2 голосов
/ 27 ноября 2015

Если у вас есть несколько элементов с одинаковым идентификатором или одним и тем же именем, просто присвойте этим классам один и тот же класс и получите доступ к ним по индексу и выполните необходимую операцию.

  <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");
0 голосов
/ 20 октября 2018

Все говорят: «Каждое значение идентификатора должно использоваться только один раз в документе», но что мы делаем, чтобы получить элементы, которые нам нужны, когда у нас есть глупая страница с более чем одним элементом с одинаковым идентификатором. Если мы используем селектор JQuery '#duplicatedId', мы получаем только первый элемент. Чтобы добиться выбора других элементов, вы можете сделать что-то вроде этого

$ ( "[ID = duplicatedId]")

Вы получите коллекцию со всеми элементами с id = duplicatedId

0 голосов
/ 03 мая 2016

Вы можете просто написать $ ('span # a'). Length, чтобы получить длину.

Вот решение для вашего кода:

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

попробуйте JSfiddle: https://jsfiddle.net/vickyfor2007/wcc0ab5g/2/

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...