Ebeveyne göre öğenin dizinini alt öğe olarak alma


160

Diyelim ki bu işaretlemem var:

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

Ve bu jQuery var:

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

Tıklarken çocuğun dizinini liebeveynine göre nasıl alabilirim li?

Örneğin, "Adım 1" i tıkladığınızda, alert"0" ile bir açılır.

Yanıtlar:


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

Ancak, her bir liste öğesi için bir tıklama işleyicisi eklemek yerine, aşağıdaki delegategibi kullanmak daha iyidir (performans açısından) :

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

JQuery 1.7+ sürümünde kullanmalısınız on. Aşağıdaki örnek, olayı #wizardbir temsilci olayı gibi çalışarak öğeye bağlar :

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

3
merhaba redsquare .. jQuery ile pratik yapıyorum, delege hakkında biraz n00b: D .. neden temsilci olayları doğrudan öğelere eklemek daha iyidir?
stecb

1
@steweb - Hey - çünkü bir olay işleyici potansiyel olarak çok daha fazla tercih edilir. Büyük listeleriniz varsa dom'a olay eklemek pahalı olabilir, bu nedenle kural olarak her öğede ayrı işleyicilerden ziyade mümkün olan her şeyi kullanmaya çalışıyorum. Daha derinleşen bir makale briancrescimanno.com/2008/05/19/… - ayrıca google 'javascript etkinlik heyeti'
redsquare

tamam, bu yüzden, olayları bu şekilde yönetmek klasik 'dom eki'nden :) daha hafif bir şeydir :) teşekkürler!
stecb

@steweb - Ayrıca daha hafiftir, çünkü jquery'nin tüm li öğelerini ilk kez aramasına gerek yoktur. Sadece kabı arar ve tıklatılan nesnenin li olup olmadığını görmek için bu düzeyde dinler.
redsquare

Bu .index yöntemi bana çok yardımcı oldu. Sıralama yapmak için jQuery Sortable kullanıyorum, ancak DOM anlamsal sıralama bilgilerini depolar. .İndex () ile sıralamayı gerçekten temiz bir şekilde dom'dan çıkarabilirim. Teşekkürler!
SimplGy

41

gibi bir şey:

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

9
Harika bir ekleme - ana seçiciye göre nispeten dizin bulabiliriz. +1
BasTaller

1
Bu cevabı, örneğin olası bir çözüm yerine soruya cevap olarak tercih edin
DarkMukke

8

Bu örneğe bir göz atın .

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

4

Bunu yapmak istemiyorsanız jQuery gibi büyük bir kütüphaneye gerek yoktur. Bunu yerleşik DOM manipülasyonu ile başarmak için li, bir dizideki kardeşlerin bir koleksiyonunu alın indexOfve tıkladığınızda o dizideki tıklanan öğeyi kontrol edin .

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>

Veya etkinlik heyeti ile:

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>

Veya, alt öğeler dinamik olarak değişebilirse (yapılacaklar listelerinde olduğu gibi), liönceden değil, her tıklamada s dizisini oluşturmanız gerekir :

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 bir işlev değil
Kareem

2
Cevabımdaki kod parçacıklarının hiçbiri bu hatayı vermiyor - çalıştıklarını görmek için "Kod parçacığını çalıştır" düğmesine basabilirsiniz. Bu hatayı
alıyorsanız

Yeterince adil. Evet, JQuery kullanıyorum. Teşekkürler
Kareem

3

Delege ve Live'ın kullanımı kolaydır, ancak dinamik olarak eklenmiş başka li'leriniz olmayacaksa, normal bağlama / tıklama ile olay gecikmesini de kullanabilirsiniz. DOM'un yeni eşleşen öğeler için izlenmesi gerekmeyeceğinden, bu yöntemi kullanırken bir miktar performans kazancı olmalıdır. Gerçek sayıları yok ama mantıklı :)

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

JsFiddle'da test edebilirsiniz: http://jsfiddle.net/jimmysv/4Sfdh/1/


1
Bu 'DOM'un izlenmesi gerekmeyecek' dediğinde neyi kastediyorsun? jq delegate dom'u izlemez.
redsquare

@redsquare Delegate'in Live'ın daha verimli bir varyantı olduğu izlenimindeydim. Bu api.jquery.com/delegate adresinden : "Belirli bir kök öğeleri kümesine bağlı olarak, şimdi veya gelecekte seçiciyle eşleşen tüm öğeler için bir veya daha fazla etkinliğe bir işleyici ekleyin." Gelecekte bağlanmak için izleme mi olmalı?
jimmystormig

Hayır, yalnızca yukarıdaki kod gibi kapta yetkilendirme kullanır. Kapsayıcıya yeni bir li öğesi eklerseniz, container click olayı tetiklenir ve her şey yine de çalışır. İzleme gerekmez.
redsquare

@redsquare Evet, haklısın. DOM yüklendikten sonra yeni öğeler eklenmiş olsa bile çözümüm çalışıyor. Delegate Live'ı dahili olarak kullandığından (bkz. Stackoverflow.com/questions/2954932/… ) hala daha optimize edilmiş ancak daha az kullanışlı gibi geliyor. Ama dediğim gibi, numaram yok.
jimmystormig

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.