Ruft den Index des Elements als untergeordnetes Element relativ zum übergeordneten Element ab


160

Angenommen, ich habe dieses Markup:

<ul id="wizard">
    <li>Step 1</li>
    <li>Step 2</li>
</ul>

Und ich habe diese jQuery:

$("#wizard li").click(function () {
    // alert index of li relative to ul parent
});

Wie kann ich den Index des Kindes lirelativ zum Elternteil erhalten, wenn ich darauf klicke li?

Wenn Sie beispielsweise auf "Schritt 1" klicken, sollte ein alertmit "0" angezeigt werden.

Antworten:


247
$("#wizard li").click(function () {
    console.log( $(this).index() );
});

Anstatt jedoch einen Klick-Handler für jedes Listenelement anzuhängen, ist es besser (leistungsmäßig), Folgendes zu verwenden delegate:

$("#wizard").delegate('li', 'click', function () {
    console.log( $(this).index() );
});

In jQuery 1.7+ sollten Sie verwenden on. Das folgende Beispiel bindet das Ereignis an das #wizardElement und funktioniert wie ein Delegatenereignis:

$("#wizard").on("click", "li", function() {
    console.log( $(this).index() );
});

3
hi redsquare .. Ich übe mit jQuery, ich bin ein bisschen n00b über delegate: D .. warum ist delegate besser als das Anhängen von Ereignissen direkt an die Elemente?
stecb

1
@steweb - Hey - weil ein Event-Handler potenziell vielen vorzuziehen ist. Das Anhängen von Ereignissen an den Dom kann teuer sein, wenn Sie große Listen haben. In der Regel versuche ich, die oben genannten Elemente nach Möglichkeit zu verwenden, anstatt einzelne Handler für jedes Element. Ein Artikel, der tiefer geht, ist briancrescimanno.com/2008/05/19/… - auch Google 'Javascript Event Delegation'
Redsquare

ok, also, Ereignisse auf diese Weise zu verwalten, ist etwas leichter als der klassische "Dom-Anhang" :) ..danke!
stecb

@steweb - Es ist auch leichter, da jquery keine erste Suche aller li-Elemente durchführen muss. Es sucht nur den Container und hört auf dieser Ebene zu, ob das angeklickte Objekt ein Li war.
Redsquare

Diese .index-Methode ist für mich sehr hilfreich. Ich verwende jQuery Sortable, um zu sortieren, aber es speichert die semantischen Ranking-Informationen im DOM. Mit .index () kann ich das Ranking wirklich sauber aus dem Dom zurückziehen. Vielen Dank!
SimplGy

41

etwas wie:

$("ul#wizard li").click(function () {
  var index = $("ul#wizard li").index(this);
  alert("index is: " + index)
});

9
Tolle Ergänzung - wir können einen Index relativ zum übergeordneten Selektor finden. +1
BasTaller

1
bevorzuge diese Antwort, da sie tatsächlich die Frage beantwortet, anstatt eine mögliche Lösung für das Beispiel
DarkMukke

8

Schauen Sie sich dieses Beispiel an .

$("#wizard li").click(function () {
    alert($(this).index()); // alert index of li relative to ul parent
});

4

Es ist nicht erforderlich, eine große Bibliothek wie jQuery zu benötigen, um dies zu erreichen, wenn Sie dies nicht möchten. Um dies mit der integrierten DOM-Manipulation zu erreichen, rufen Sie eine Sammlung der liGeschwister in einem Array ab und überprüfen Sie beim Klicken indexOfdas angeklickte Element in diesem Array.

const lis = [...document.querySelectorAll('#wizard > li')];
lis.forEach((li) => {
  li.addEventListener('click', () => {
    const index = lis.indexOf(li);
    console.log(index);
  });
});
<ul id="wizard">
    <li>Step 1</li>
    <li>Step 2</li>
</ul>

Oder mit Veranstaltungsdelegation:

const lis = [...document.querySelectorAll('#wizard li')];
document.querySelector('#wizard').addEventListener('click', ({ target }) => {
  // Make sure the clicked element is a <li> which is a child of wizard:
  if (!target.matches('#wizard > li')) return;
  
  const index = lis.indexOf(target);
  console.log(index);
});
<ul id="wizard">
    <li>Step 1</li>
    <li>Step 2</li>
</ul>

Wenn sich die untergeordneten Elemente dynamisch ändern (wie bei einer Aufgabenliste), müssen Sie das Array von lis bei jedem Klick erstellen und nicht vorher:

const wizard = document.querySelector('#wizard');
wizard.addEventListener('click', ({ target }) => {
  // Make sure the clicked element is a <li>
  if (!target.matches('li')) return;
  
  const lis = [...wizard.children];
  const index = lis.indexOf(target);
  console.log(index);
});
<ul id="wizard">
    <li>Step 1</li>
    <li>Step 2</li>
</ul>


$ (...). indexOf ist keine Funktion
Kareem

2
Keines der Code-Snippets in meiner Antwort erzeugt diesen Fehler. Sie können auf "Code-Snippet ausführen" klicken, um zu sehen, ob sie funktionieren. Wenn Sie diesen Fehler erhalten, verwenden Sie anderen Code - es hört sich so an, als würden Sie jQuery verwenden, aber meine Antwort zeigt, wie Sie so etwas ohne jQuery erreichen können
CertainPerformance

Meinetwegen. Ja, ich verwende JQuery. Danke
Kareem

3

Delegate und Live sind einfach zu verwenden, aber wenn Sie keine dynamischen Li: s mehr hinzufügen möchten, können Sie die Ereignisverzögerung auch mit normalem Binden / Klicken verwenden. Mit dieser Methode sollte ein gewisser Leistungsgewinn erzielt werden, da das DOM nicht auf neue übereinstimmende Elemente überwacht werden muss. Ich habe keine tatsächlichen Zahlen, aber es macht Sinn :)

$("#wizard").click(function (e) {
    var source = $(e.target);
    if(source.is("li")){
        // alert index of li relative to ul parent
        alert(source.index());
    }
});

Sie können es unter jsFiddle testen: http://jsfiddle.net/jimmysv/4Sfdh/1/


1
Worauf beziehen Sie sich, wenn Sie sagen, dass "DOM nicht überwacht werden muss"? jq delegate überwacht den dom nicht.
Redsquare

@redsquare Ich hatte den Eindruck, dass Delegate nur eine effizientere Variante von Live ist. Dies ist von api.jquery.com/delegate : "Hängen Sie einen Handler an ein oder mehrere Ereignisse für alle Elemente an, die jetzt oder in Zukunft mit dem Selektor übereinstimmen, basierend auf einem bestimmten Satz von Stammelementen." Es muss überwacht werden, um in Zukunft zu binden?
Jimmyystormig

Nein, es wird nur eine Delegierung für den Container verwendet, wie in Ihrem obigen Code. Wenn Sie ein neues li-Element in den Container einfügen, wird das Container-Klickereignis weiterhin ausgelöst und alles funktioniert weiterhin. Keine Überwachung erforderlich.
Redsquare

@redsquare Ja, du bist richtig. Meine Lösung funktioniert auch dann, wenn nach dem Laden des DOM neue Elemente hinzugefügt werden. Da Delegate Live intern verwendet (siehe stackoverflow.com/questions/2954932/… ), scheint dies immer noch optimierter, aber weniger bequem zu sein. Aber wie gesagt, ich habe keine Zahlen.
Jimmyystormig

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.