กำลังมองหาวิธี jQuery find (.. ) ที่มีโหนดปัจจุบัน


140

วิธีการข้ามผ่านjQuery find (.. )ไม่รวมโหนดปัจจุบัน - เริ่มต้นด้วยลูกของโหนดปัจจุบัน วิธีใดที่ดีที่สุดในการเรียกการดำเนินการค้นหาที่มีโหนดปัจจุบันในอัลกอริทึมการจับคู่ เมื่อมองผ่านเอกสารไม่มีอะไรกระโดดมาที่ฉันทันที

คำตอบ:


158

สำหรับ jQuery 1.8 ขึ้นไปคุณสามารถใช้.addBack()ไฟล์. ต้องใช้ตัวเลือกดังนั้นคุณจึงไม่จำเป็นต้องกรองผลลัพธ์:

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

ก่อนหน้า jQuery 1.8 คุณติดอยู่.andSelf()(ตอนนี้เลิกใช้งานและลบออกแล้ว) ซึ่งจำเป็นต้องมีการกรอง:

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

5
ฉันได้รวมสิ่งนี้เป็นปลั๊กอิน jquery.findIncludeSelf ลงทะเบียนกับ bower ดูgithub.com/ronen/jquery.findIncludeSelf
ronen

18
@ronen ไฟล์พิเศษสำหรับบางสิ่งที่สามารถทำได้ในบรรทัดเดียว? ขอบคุณ แต่ไม่ขอบคุณ

6
@ prc322 ไฟล์พิเศษไม่รบกวนฉันสำหรับการปรับใช้ซึ่งรวม javascript ทั้งหมดไว้ในไฟล์เดียว โดยทั่วไปฉันชอบใช้เมธอดไลบรารี (ทดสอบ) แม้กระทั่งกับสิ่งง่ายๆมากกว่าที่จะทำให้โค้ดของฉันยุ่งเหยิงด้วยสิ่งที่ฉันอ่านยากกว่าและแนะนำความเป็นไปได้มากขึ้นสำหรับข้อบกพร่อง ในกรณีนี้โดยเฉพาะอย่างยิ่ง IMHO จำเป็นต้องระบุ'selector'สองครั้งทำให้การห่อหุ้มเป็นที่ต้องการมากขึ้น YMMV
ronen

โอเคฉันอาจจะหนา แต่ไม่ต้องระบุ'selector'สองครั้ง (ตามที่ @ronen กล่าวไว้) ใช้ไม่ได้เหรอobject.parent().find('selector')??? - อย่างที่บอกว่าฉันชอบไอเดียของ lib ที่ทำเพื่อคุณ
แซม

8
@ circa1983 object.parent().find('selector')รวมถึงพี่น้องobjectและลูกหลานของพวกเขา
Robert

41

คุณไม่สามารถทำสิ่งนี้ได้โดยตรงสิ่งที่ใกล้เคียงที่สุดที่ฉันคิดได้คือการใช้.andSelf()และการโทร.filter()เช่นนี้:

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

น่าเสียดายที่.andSelf()ไม่มีตัวเลือกซึ่งจะมีประโยชน์


7
คุณได้เพิ่มความคิดเห็นในหน้า jquery ทันทีหลังจากตอบคำถามนี้api.jquery.com/andSelf/#comment-50124533ตอนนี้เป็นความละเอียดถี่ถ้วน ดี! ฉันได้ตรวจสอบสถานะของฉันและ 'ชอบ' สิ่งนั้นด้วย
John K

2
อันที่สองจะช้าอย่างเหลือเชื่อ อย่างแรกก็แค่ช้า
Tgr

@Tgr - ฉันไม่เห็นด้วย แต่แรกไม่ควรจะแสดงว่าถ้าคุณกำลังจัดการกับมากจำนวนมากขององค์ประกอบ หากคุณไม่จำเป็นต้องเชื่อมโยงคุณสามารถข้ามการกรององค์ประกอบเหล่านั้นซ้ำได้อย่างแน่นอน
Nick Craver

3
ที่น่าสนใจคือclosest(..)รวมองค์ประกอบ DOM ปัจจุบันและขึ้นต้นไม้ในขณะที่วิธีการข้ามผ่านแบบลงต้นไม้ทั้งหมดเช่นfind(..)ฯลฯ ไม่ตรงกับองค์ประกอบปัจจุบัน เหมือนกับว่าทีม jQuery ใช้สิ่งเหล่านี้โดยมีจุดประสงค์เพื่อไม่ให้เกิดการทับซ้อนกันเมื่อการดำเนินการทั้งสองใช้ร่วมกันสำหรับการค้นหาแนวตั้งแบบเต็ม
John K

17
โปรดทราบว่า. andSelf () ได้เลิกใช้แล้วเมื่อ v1.8 และแทนที่ด้วย. addBack () ที่ใช้ตัวเลือกเป็นอาร์กิวเมนต์ ดูapi.jquery.com/addBack
kkara

9

กำหนด

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

จากนั้นใช้

$.findSelf(selector);

แทน

$find(selector);

น่าเศร้าที่ jQuery ไม่มีในตัวนี้ แปลกจริงๆสำหรับการพัฒนาหลายปี ตัวจัดการ AJAX ของฉันไม่ได้นำไปใช้กับองค์ประกอบยอดนิยมบางอย่างเนื่องจาก. find () ทำงาน


นี่คือบั๊กกี้ มันเพิ่ม "ตัวเอง" ทั้งหมดแม้ว่าจะมีเพียงตัวเดียวเท่านั้นที่ตรงกัน ... - สาเหตุหนึ่งที่ทำให้เกิดข้อบกพร่องนี้คือเมธอด jQuery ที่ชื่อบ้าคลั่ง ...
Robert Siemer

ฉันพยายามแก้ไขข้อบกพร่องที่คุณรายงาน ตอนนี้ทำงานได้ถูกต้องหรือไม่
Dmitriy Sintsov

คำตอบอื่น ๆ ส่วนใหญ่ใช้ที่filter()นั่นซึ่งเข้าท่ากว่า
Robert Siemer

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

คุณสามารถจัดเก็บ$('selector')ตัวแปรเพื่อเร่งความเร็ว คุณสามารถเขียนฟังก์ชันที่กำหนดเองสำหรับสิ่งนี้ได้หากคุณต้องการมันมาก:

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

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

สิ่งนี้ใช้ได้เฉพาะเมื่อคุณเริ่มต้นด้วยตัวเลือกซึ่งอาจไม่เป็นเช่นนั้น นอกจากนี้ก็ไม่ถูกต้องก็จะเป็นสิ่งที่คุณมีในขณะนี้จะเทียบเท่ากับ$('selector').find('otherSelector').add($('otherSelector')) .andSelf()สุดท้าย.andFind()ไม่ได้กรองตามนิพจน์คุณจะต้อง.add($(this).filter(expr)):)
Nick Craver

@Nick Craver: ใช่ฉันลืมส่วนการกรองได้รับการแก้ไขแล้ว ไม่สำคัญว่า$('selector')จะถูกแทนที่ด้วยวิธีการอื่นในการรับวัตถุ jQuery หรือไม่ (หากนั่นคือสิ่งที่คุณหมายถึงโดยไม่ได้เริ่มต้นด้วยตัวเลือก) add()สามารถจัดการกับสิ่งใดก็ได้เช่น$()กัน
Tgr

ประเด็นของฉันคือคุณ$('selector')อาจจะ$('selector').children('filter').closest('.class').last()... มันอาจอยู่ในห่วงโซ่และคุณไม่รู้ว่าวัตถุที่คุณกำลังเพิ่มคืออะไรดังนั้นวิธีการแก้ปัญหาทั่วไปควรใช้วัตถุก่อนหน้าเช่นเดียวกับตัวกรอง :)
Nick Craver

ฉันยังไม่เห็นว่าทำไมถึงเป็นปัญหา thisเป็นวัตถุ jQuery ที่เรียกใช้ปลั๊กอิน อาจเป็นผลมาจากห่วงโซ่การโทร
Tgr

5

คำตอบที่ได้รับการยอมรับนั้นไม่มีประสิทธิภาพมากและกรองชุดขององค์ประกอบที่ตรงกันแล้ว

//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

หากคุณต้องการให้โซ่ทำงานอย่างถูกต้องให้ใช้ข้อมูลโค้ดด้านล่าง

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

หลังจากการเรียกใช้ฟังก์ชันสิ้นสุดจะส่งคืนองค์ประกอบ #foo

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

หากไม่มีการกำหนดปลั๊กอินพิเศษคุณจะติดอยู่กับสิ่งนี้

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

อ่าไม่ ... ถ้าthisมีมากกว่าหนึ่งองค์ประกอบthis.is()ก็พอใจแล้วถ้ามีเพียงหนึ่งในนั้นที่ตรงกัน
Robert Siemer

3

ในกรณีที่คุณกำลังมองหาองค์ประกอบเดียวไม่ว่าจะเป็นองค์ประกอบปัจจุบันหรือองค์ประกอบภายในคุณสามารถใช้:

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

ในกรณีที่คุณกำลังมองหาองค์ประกอบหลายอย่างคุณสามารถใช้ได้:

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

การใช้andSelf/ andBackค่อนข้างหายากไม่แน่ใจว่าทำไม บางทีอาจเป็นเพราะปัญหาด้านการแสดงที่ผู้ชายบางคนพูดถึงก่อนหน้าฉัน

(ตอนนี้ฉันสังเกตว่าTgrได้ให้โซลูชันที่สองนั้นแล้ว)


2

ฉันรู้ว่านี่เป็นคำถามเก่า แต่มีวิธีที่ถูกต้องกว่านี้ หากลำดับมีความสำคัญตัวอย่างเช่นเมื่อคุณจับคู่ตัวเลือกที่ชอบ:firstฉันได้เขียนฟังก์ชันเล็ก ๆ น้อย ๆ ที่จะส่งคืนผลลัพธ์เหมือนกับที่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);
};

มันจะไม่มีประสิทธิภาพ แต่อย่างใด แต่เป็นสิ่งที่ดีที่สุดที่ฉันคิดขึ้นมาเพื่อรักษาระเบียบที่เหมาะสม


1

ฉันคิดว่าandSelfคือสิ่งที่คุณต้องการ:

obj.find(selector).andSelf()

โปรดทราบว่าสิ่งนี้จะเพิ่มกลับโหนดปัจจุบันเสมอไม่ว่าจะตรงกับตัวเลือกหรือไม่ก็ตาม



0

ฉันพยายามหาวิธีแก้ปัญหาที่ไม่ทำซ้ำ (เช่นไม่ป้อนตัวเลือกเดียวกันสองครั้ง)

และส่วนขยาย jQuery เล็ก ๆ นี้ทำ:

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

มันรวมfind()(ลูกหลานเท่านั้น) กับfilter()(เฉพาะชุดปัจจุบัน) และสนับสนุนข้อโต้แย้งใด ๆ ที่ทั้งคู่กิน pushStack()ช่วยให้.end()การทำงานเป็นไปตามคาด

ใช้แบบนี้:

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

-2

นี่คือความจริงที่ถูกต้อง (แต่น่าเศร้า):

$(selector).parent().find(oSelector).filter($(selector).find('*'))

http://jsfiddle.net/SergeJcqmn/MeQb8/2/


ไม่ทำงานกับโหนดแยก (และตัวเอกสารเอง) อย่างไรก็ตาม
John Dvorak

2
เอ่อไม่นี่จะเป็นการลบ$(selector)ตัวเองออกจากฉากในทุกกรณี
John Dvorak
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.