2011-12-14 16 views
53

GoogleのAdWordsウェブサイトから、複数の要素が同じidのデータを取得します。同じ「id」を持つ要素が複数ある場合のjQueryの動作は?

なぜ次の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 
}); 

答えて

66

は、同じIDを持つ2つの要素を有するW3C仕様に従って有効なHTMLではありません。

CSSセレクタにIDセレクタしかない場合(特定のコンテキストで使用されていない場合)、jQueryはネイティブdocument.getElementByIdメソッドを使用します。このメソッドは、そのIDを持つ最初の要素のみを返します。

しかし、他の2つのインスタンスでは、jQueryはSizzleセレクタエンジン(使用可能であればquerySelectorAll)に依存しています。これは明らかに両方の要素を選択します。結果はブラウザごとに異なる場合があります。

ただし、同じIDで同じページに2つの要素を使用しないでください。 CSS用に必要な場合は、代わりにクラスを使用してください。 http://jsfiddle.net/P2j3f/2/

注:可能ならば、あなたは資格がなければならない

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

がフィドルを見てみましょう:あなたは絶対に重複したIDによって選択する必要がある場合は


、属性セレクタを使用タグセレクタを備えたそのセレクタ:

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

あなたは**注を説明してくださいでした:

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

JSfiddleを試してみてください。ここで

はあなたのコードのためのソリューションですか?タグセレクタを追加すると便利なのはいつですか? –

+4

@Misha Moroshko - 可能な限り、タグセレクタを含める必要があります。これは、タグセレクタが属性セレクタよりもはるかに効率的であるためです。属性セレクタをタグセレクタで修飾すると、jQueryはまずタグセレクタを使用してそのタグを持つ要素を見つけ、それらの要素に対してのみ属性セレクタを実行します。これははるかに効率的です。 –

+2

私は 'div#some_id'が'#some_id'より遅いことをここで見ています:http://stackoverflow.com/q/7262116/247243 –

3

与えられたidを持つ要素が1つだけあるべきです。あなたがその状況に悩まされているなら、オプションの私の答えの後半を見てください。

同じ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セレクタエンジンを使用して、独自の実装を持つセレクタを手動で検索します。したがって、正確なセレクタとブラウザの新しさに応じて、同じブラウザファミリ内に少なくとも3つの異なる実装を持つことができます。次に、個々のブラウザにはそれぞれ独自のquerySelectorAll()実装があります。このような状況に確実に対処したい場合は、上に示したように独自の反復コードを使用する必要があります。

+0

彼はできません。彼はGoogleからそれを得ている、それは問題だ –

+0

@RalphLavelle - 私はあなたがそれにこだわっている場合は、dupのIDを扱う方法を追加しました。 – jfriend00

2

jQueryのidセレクタは1つの結果しか返しません。 2番目と3番目のステートメントの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; 

声明は...また、二つの結果が得られます。 id Selector jQuery pageから

2

各ID値は、文書内に一度だけ使用する必要があります。複数の要素に同じIDが割り当てられている場合、そのIDを使用するクエリはDOMで最初に一致する要素のみを選択します。しかし、この動作は信頼されるべきではありません。同じIDを使用する複数の要素を持つドキュメントは無効です。

Naughty Google。しかし、彼らは私が聞いている<html><body>タグを閉じない。質問は、なぜMishaの2番目と3番目のクエリが2でなく、1でないかを返す理由です。

0

同じ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"); 
関連する問題