Подтвердить что ты не робот

Как работает jQuery, когда есть несколько элементов с одним и тем же "id"?

Я извлекаю данные с веб-сайта 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
});
4b9b3361

Ответ 1

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

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

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

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


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

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

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

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

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

Ответ 2

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

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

Ответ 3

Селектор

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;

... Также дает два результата.

Ответ 4

На странице id Selector jQuery:

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

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

Ответ 5

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

  <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

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

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

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

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