Mevcut düğümü içeren jQuery find (..) yöntemi aranıyor


134

JQuery find (..) geçiş yöntemi geçerli düğümü içermez - geçerli düğümün çocuklarıyla başlar. Eşleştirme algoritmasında mevcut düğümü içeren bir bulma işlemini çağırmanın en iyi yolu nedir? Dokümanlara baktığımda hiçbir şey hemen aklıma gelmiyor.

Yanıtlar:


153

JQuery 1.8 ve üstü için kullanabilirsiniz .addBack(). Bir seçici alır, böylece sonucu filtrelemenize gerek kalmaz:

object.find('selector').addBack('selector')

JQuery 1.8'den önce .andSelf(), daha sonra filtreleme gerektiren (artık kullanımdan kaldırıldı ve kaldırıldı) takılı kaldınız:

object.find('selector').andSelf().filter('selector')

5
Bunu, bower ile kayıtlı jquery.findIncludeSelf eklentisi olarak bir araya getirdim. Bkz. Github.com/ronen/jquery.findIncludeSelf
ronen

18
@ronen Tek satırda yapılabilecek bir şey için fazladan bir dosya? Teşekkürler ama hayır teşekkürler.

6
@ prc322 Fazladan bir dosya, tüm javascript'i tek bir dosyada toplayan dağıtımlar için beni rahatsız etmiyor. Genel olarak, kodumu okumayı daha zor bulduğum ve böcekler için daha fazla olasılık sağlayan şeylerle karıştırmak yerine, basit şeyler için bile kitaplık yöntemlerini kullanmayı tercih ederim. Bu durumda özellikle, IMHO'nun 'selector'iki kez belirtme ihtiyacı , kapsüllemeyi ekstra arzu edilir kılar. YMMV
ronen

Tamam, bu yüzden kalın olabilirim ama 'selector'iki kez belirtmek zorunda değilsin (@ronen tarafından belirtildiği gibi), sadece kullanamaz mısın object.parent().find('selector')??? - bunu sizin için yapan bir kitaplık fikrini sevdiğim söyleniyor.
Sam

8
@ circa1983 object.parent().find('selector'), kardeşlerini objectve onların torunlarını içerir.
Robert

41

Bunu doğrudan yapamazsınız, aklıma en yakın olan kullanmak .andSelf()ve aramaktır .filter(), şöyle:

$(selector).find(oSelector).andSelf().filter(oSelector)
//or...
$(selector).find('*').andSelf().filter(oSelector);

Maalesef .andSelf()kullanışlı olacak bir seçici almıyor.


7
Bu soruyu yanıtladıktan hemen sonra jquery sayfasına bir yorum bile eklediniz api.jquery.com/andSelf/#comment-50124533 İşte bu tamlık . Güzel! Durum tespiti yaptım ve bunu da 'Beğendim'.
John K

2
İkincisi, akıllara durgunluk verecek derecede yavaş olacaktır. Birincisi sadece yavaştır.
Tgr

@Tgr - Buna katılmıyorum, ancak çok fazla sayıda unsurla uğraşmadığınız sürece ilki o gösteri olmamalı . Zincirlemeniz gerekmiyorsa, bu öğeleri kesinlikle yeniden filtrelemeyi atlayabilirsiniz.
Nick Craver

3
İlginç bir şekilde, closest(..)geçerli DOM öğesini içerir ve ağacın yukarısını içerir, oysa find(..)vb. Gibi ağaçtan aşağı geçiş yöntemleri mevcut öğeyle eşleşmez. Sanki jQuery ekibi, tam bir dikey arama için her iki işlem birlikte kullanıldığında, bunları bilerek çakışma olmadan uyguluyor.
John K

17
.AndSelf () 'in v1.8'den itibaren kullanımdan kaldırıldığını ve bağımsız değişken olarak bir seçiciyi alan .addBack () ile değiştirildiğini unutmayın. Bkz. Api.jquery.com/addBack
kkara

9

Tanımlamak

$.fn.findSelf = function(selector) {
    var result = this.find(selector);
    this.each(function() {
        if ($(this).is(selector)) {
            result.add($(this));
        }
    });
    return result;
};

sonra kullan

$.findSelf(selector);

onun yerine

$find(selector);

Ne yazık ki jQuery'nin bu yerleşik özelliği yok. Yıllarca süren geliştirme için gerçekten garip. AJAX işleyicilerim, .find () işlevinin nasıl çalıştığı nedeniyle bazı üst öğelere uygulanmadı.


Bu adamcağız. Yalnızca biri eşleşse bile "benliğin" tümünü ekler ... - Bu hatanın bir nedeni, berbat bir şekilde adlandırılmış jQuery yöntemidir ...
Robert

Bildirdiğiniz hatayı düzeltmeye çalıştım. Şimdi düzgün çalışıyor mu?
Dmitriy Sintsov

Diğer cevapların çoğu filter()burada kullanılır, bu daha mantıklıdır.
Robert Siemer

5
$('selector').find('otherSelector').add($('selector').filter('otherSelector'))

$('selector')Hızlandırmak için bir değişkende saklayabilirsiniz . Çok ihtiyacınız varsa bunun için özel bir işlev bile yazabilirsiniz:

$.fn.andFind = function(expr) {
  return this.find(expr).add(this.filter(expr));
};

$('selector').andFind('otherSelector')

Bu, yalnızca bir seçici ile başlıyorsanız işe yarar , ancak durum böyle olmayabilir. Ayrıca, bu yanlış olacaktır $('selector').find('otherSelector').add($('otherSelector')), şu anda sahip olduğunuz şeye eşdeğerdir .andSelf(). Son olarak, .andFind()ifadeye göre filtreleme yapmaz, yapmanız gerekir .add($(this).filter(expr)):)
Nick Craver

@Nick Craver: evet, filtreleme kısmını unuttum, şimdi düzeltildi. $('selector')Bir jQuery nesnesi elde etmenin başka bir yöntemiyle değiştirilip değiştirilmemesi gerçekten önemli değil (eğer bir seçici ile başlamayarak kastettiğin buysa), add()her şeyi olabildiğince $()halledebilir.
Tgr

Demek istediğim şu ki, senin $('selector')olabilir $('selector').children('filter').closest('.class').last()... bir zincirde olabilir ve eklediğiniz nesnenin ne olduğu hakkında hiçbir fikriniz yok, bu nedenle genel çözüm önceki nesneyi filtrenin yaptığı gibi almalıdır :)
Nick Craver

Hala bunun neden bir sorun olduğunu anlamıyorum. thiseklentinin çağrıldığı jQuery nesnesidir. Bir çağrı zincirinin sonucu da olabilir.
Tgr

5

Kabul edilen cevap çok verimsizdir ve zaten eşleşen öğeler kümesini filtreler.

//find descendants that match the selector
var $selection = $context.find(selector);
//filter the parent/context based on the selector and add it
$selection = $selection.add($context.filter(selector);

3

Zincirlemenin düzgün çalışmasını istiyorsanız aşağıdaki parçacığı kullanın.

$.fn.findBack = function(expr) {
    var r = this.find(expr);
    if (this.is(expr)) r = r.add(this);
    return this.pushStack(r);
};

End işlevi çağrıldıktan sonra #foo öğesini döndürür.

$('#foo')
    .findBack('.red')
        .css('color', 'red')
    .end()
    .removeAttr('id');

Fazladan eklenti tanımlamadan, buna bağlı kalırsınız.

$('#foo')
    .find('.red')
        .addBack('.red')
            .css('color', 'red')
        .end()
    .end()
    .removeAttr('id');

Ah, hayır ... Eğer thisbirden fazla öğe this.is()varsa, bunlardan sadece biri eşleşirse zaten tatmin olur.
Robert Siemer

3

Mevcut veya içindeki bir öğe olmak üzere tam olarak bir öğe arıyorsanız , şunları kullanabilirsiniz:

result = elem.is(selector) ? elem : elem.find(selector);

Birden fazla öğe arıyorsanız, şunları kullanabilirsiniz:

result = elem.filter(selector).add(elem.find(selector));

andSelf/ Kullanımı andBackoldukça nadirdir, neden olduğundan emin değilim. Belki de bazılarının benden önce bahsettiği performans sorunları yüzünden.

( Tgr'nin o ikinci çözümü zaten verdiğini şimdi fark ettim )


2

Bunun eski bir soru olduğunu biliyorum ama daha doğru bir yol var. Sıra önemliyse, örneğin bir seçici ile eşleştiriyorsanız , mevcut öğe kümesini gerçekten içeriyormuş :firstgibi tam olarak aynı sonucu döndürecek küçük bir işlev yazdım find():

$.fn.findAll = function(selector) {
  var $result = $();

  for(var i = 0; i < this.length; i++) {
    $result = $result.add(this.eq(i).filter(selector));
    $result = $result.add(this.eq(i).find(selector));
  }

  return $result.filter(selector);
};

Hiçbir şekilde verimli olmayacak, ancak doğru düzeni sağlamak için bulduğum en iyisi bu.


1

Sanırım andSelfistediğin şey bu:

obj.find(selector).andSelf()

Seçiciyle eşleşsin veya eşleşmesin, bunun her zaman geçerli düğümü geri ekleyeceğini unutmayın.


1

Mevcut düğümlere kesinlikle bakıyorsanız, yapmanız gereken sadece

$(html).filter('selector')

0

Kendini tekrar etmeyen bir çözüm bulmaya çalışıyordum (yani aynı seçiciye iki kez girmiyorum).

Ve bu küçük jQuery uzantısı bunu yapıyor:

jQuery.fn.findWithSelf = function(...args) {
  return this.pushStack(this.find(...args).add(this.filter(...args)));
};

find()(Yalnızca torunları) filter()(yalnızca mevcut küme) ile birleştirir ve her ikisinin de yediği argümanları destekler. pushStack()Sağlar .end()beklendiği gibi çalışmaya.

Bunun gibi kullanın:

$(element).findWithSelf('.target')

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.