ฉันจะตรวจสอบว่าองค์ประกอบ jQuery อยู่ใน DOM ได้อย่างไร


147

สมมติว่าฉันกำหนดองค์ประกอบ

$foo = $('#foo');

แล้วฉันจะโทร

$foo.remove()

จากบางเหตุการณ์ คำถามของฉันคือฉันจะตรวจสอบว่า $ foo ถูกลบออกจาก DOM ได้อย่างไรหรือไม่ ฉันพบว่า$foo.is(':hidden')การทำงาน $foo.hide()แต่ที่จะแน่นอนยังกลับจริงถ้าฉันเพียงเรียกว่า

คำตอบ:


238

แบบนี้:

if (!jQuery.contains(document, $foo[0])) {
    //Element is detached
}

สิ่งนี้จะยังคงใช้งานได้หากหนึ่งในองค์ประกอบพาเรนต์ขององค์ประกอบถูกลบ (ในกรณีที่องค์ประกอบนั้นจะยังคงมีพาเรนต์)


14
การทำ$foo.closest(document.documentElement)เร็วขึ้น (ถ้าใครสนใจjsperf.com/jquery-element-in-dom )
urraka

48
@PerroAzul: ฉันพบทางเลือกที่เร็วกว่ามาก : jsperf.com/jquery-element-in-dom/2
SLaks

3
ประสิทธิภาพเป็นสิ่งที่ฉันกังวลในทันทีด้วยวิธีนี้ขอบคุณสำหรับการเชื่อมโยงมาตรฐาน @SLaks ดังนั้นดูเหมือนว่า$.contains(document.documentElement, $foo.get(0))เป็นวิธีที่เร็วที่สุด
Christof

10
มีวิธี DOM ที่บริสุทธิ์ในการทำสิ่งนี้ซึ่งอ่านง่ายกว่าและฉันคิดว่าคล้ายกันมากในแง่ของประสิทธิภาพ:document.contains($foo[0])
Joel Cross

3
ทั้งหมดนี้พูดถึงการแสดง ... การวัดประสิทธิภาพแสดงวิธีหนึ่งที่ใช้เวลา 15 ไมโครวินาทีและอีกวิธีหนึ่งใช้เวลา 0.15 ไมโครวินาที แต่จริงๆแล้วใครจะสน - คุณจะไม่สังเกตเห็นความแตกต่างใด ๆ เว้นแต่คุณจะทำมันเป็นแสนครั้ง และมันอาจเปลี่ยนแปลงได้ทั้งหมดหาก jQuery หรือเอ็นจิ้น JavaScript ได้รับการปรับให้เหมาะสมเพียงใช้วิธีการใดก็ตามที่อ่านได้ดีกว่าสำหรับคุณและใครก็ตามที่ต้องรักษาโค้ดของคุณในอนาคต
James


5

ฉันเพิ่งรู้คำตอบเมื่อฉันพิมพ์คำถามของฉัน: โทร

$foo.parent()

หาก$f00ได้รับการออกจาก DOM $foo.parent().length === 0แล้ว มิฉะนั้นความยาวของมันจะเป็นอย่างน้อย 1

[แก้ไข: สิ่งนี้ไม่ถูกต้องทั้งหมดเนื่องจากองค์ประกอบที่ลบออกยังคงมีแม่ได้ ตัวอย่างเช่นหากคุณลบ a <ul>ลูกของแต่ละคน<li>จะยังมีผู้ปกครองอยู่ ใช้คำตอบ SLaks แทน


2
... ยกเว้นว่าโหนดที่ถูกลบออกไม่ใช่ลูกคนเดียว
ÁlvaroGonzález

@ Álvaro - ทำไมมันถึงสำคัญ
user113716

@patrick: ฉันคิดถึงอะไรเหรอ? คุณจะมั่นใจได้อย่างไรว่า $ foo.parent () ความยาวมากกว่าศูนย์
ÁlvaroGonzález

@ Álvaro - OP กำลังทดสอบเพื่อให้แน่ใจว่า$fooถูกลบออกจาก DOM หากลบเรียบร้อยแล้วจะไม่มีองค์ประกอบหลักอีกต่อไป ดังนั้น$foo.parent().length === 0หมายความว่าการลบสำเร็จ
user113716

1
$ foo.closest ("body") จะเป็นการแก้ไขสำหรับเทคนิคนี้
georgephillips

4

เนื่องจากฉันไม่สามารถตอบเป็นความคิดเห็นได้ (กรรมต่ำเกินไปฉันเดา) นี่คือคำตอบแบบเต็ม วิธีที่เร็วที่สุดคือง่ายต่อการยกเลิกการตรวจสอบ jQuery สำหรับการสนับสนุนเบราว์เซอร์และโกนปัจจัยที่มีค่าน้อยที่สุด

เท่าที่เห็นที่นี่ - http://jsperf.com/jquery-element-in-dom/28 - รหัสจะมีลักษณะเช่นนี้:

var isElementInDOM = (function($) {
  var docElt = document.documentElement, find,
      contains = docElt.contains ?
        function(elt) { return docElt.contains(elt); } :

        docElt.compareDocumentPosition ?
          function(elt) {
            return docElt.compareDocumentPosition(elt) & 16;
          } :
          ((find = function(elt) {
              return elt && (elt == docElt || find(elt.parentNode));
           }), function(elt) { return find(elt); });

  return function(elt) {
    return !!(elt && ((elt = elt.parent) == docElt || contains(elt)));
  };
})(jQuery);

สิ่งนี้เทียบเท่ากับ jQuery.contain (document.documentElement, elt [0])


3

อาจเป็นวิธีที่ performative ที่สุดคือ:

document.contains(node); // boolean

สิ่งนี้ใช้ได้กับ jQuery:

document.contains($element[0]); // var $element = $("#some-element")
document.contains(this[0]); // in contexts like $.each(), `this` is the jQ object

ที่มาจาก MDN

บันทึก:


มีใครบ้างที่ดูคำตอบนี้ คำตอบที่ดี +1 (ฉัน sugested ฉบับขอบคุณ)
Guilherme Nascimento

1

ฉันชอบวิธีนี้ ไม่มี jQuery และไม่มีการค้นหา DOM ขั้นแรกให้ค้นหาผู้ปกครองชั้นนำ (บรรพบุรุษ) จากนั้นดูว่านั่นคือ documentElement หรือไม่

function ancestor(HTMLobj){
  while(HTMLobj.parentElement){HTMLobj=HTMLobj.parentElement}
  return HTMLobj;
}
function inTheDOM(obj){
  return ancestor(obj)===document.documentElement;
}

1

แทนการทำซ้ำผู้ปกครองคุณสามารถรับ rect bounding ซึ่งเป็นศูนย์ทั้งหมดเมื่อองค์ประกอบถูกแยกจาก dom

function isInDOM(element) {
    var rect=element.getBoundingClientRect();
    return (rect.top || rect.bottom || rect.height || rect.width)?true:false;
}

ถ้าคุณต้องการที่จะจัดการกับกรณีขอบขององค์ประกอบความกว้างและความสูงเป็นศูนย์ที่ด้านบนเป็นศูนย์และซ้ายเป็นศูนย์คุณสามารถตรวจสอบซ้ำโดยผู้ปกครองซ้ำจนถึงเอกสาร


แม้ว่าข้อมูลโค้ดนี้อาจช่วยแก้ปัญหาได้ แต่ก็ไม่ได้อธิบายว่าทำไมหรือตอบคำถามอย่างไร โปรดระบุคำอธิบายสำหรับรหัสของคุณเนื่องจากช่วยปรับปรุงคุณภาพการโพสต์ของคุณได้อย่างแท้จริง จำไว้ว่าคุณกำลังตอบคำถามสำหรับผู้อ่านในอนาคตและคนเหล่านั้นอาจไม่ทราบสาเหตุของการแนะนำรหัสของคุณ ผู้ตั้งค่าสถานะ / ผู้ตรวจทาน: สำหรับคำตอบที่ใช้รหัสอย่างเช่น downvote อย่าลบ!
Luca Kiebel

สิ่งนี้ไม่รู้จักองค์ประกอบที่ซ่อนอยู่ว่า "ไม่อยู่ใน DOM" หรือไม่ เช่นองค์ประกอบที่display: noneไม่มีขอบเขตผูกทั้ง
ฟิลิป

0

เห็นด้วยกับความคิดเห็นของ Perro มันสามารถทำได้เช่นนี้

$foo.parents().last().is(document.documentElement);

0
jQuery.fn.isInDOM = function () {
   if (this.length == 1) {
      var element = this.get(0);
      var rect = element.getBoundingClientRect();
      if (rect.top + rect.bottom + rect.width + rect.height + rect.left + rect.right == 0)
         return false;
      return true;
   }
   return false;
};

-1

ทำไมไม่เพียง: if( $('#foo').length === 0)...?


@stevematdavies คำถามคือ "วิธีการทดสอบว่าองค์ประกอบในวัตถุ jQuery ที่กำหนดอยู่ใน DOM" ไม่ใช่ "วิธีทดสอบว่าองค์ประกอบที่ตรงกับสตริงตัวเลือกที่กำหนดอยู่ใน DOM หรือไม่"
เทรเวอร์เบิร์นแฮม

@TrevorBurnham: ในทุกความเป็นธรรมการสอบถามซ้ำโดยใช้ตัวเลือกที่ใช้ในการสร้าง$fooและตรวจสอบว่าการสอบถามซ้ำอีกครั้งตรงกับองค์ประกอบใด ๆ ดูเหมือนว่าจะเป็นวิธีการแก้ปัญหาที่ทำงานได้ในหลายสถานการณ์ อาจเร็วกว่าโซลูชันอื่น ๆ เนื่องจากวิธีการทั้ง jQuery และเบราว์เซอร์เพิ่มประสิทธิภาพตัวเลือกบางตัว (เช่นโดย ID)
Matt

@Matt $ foo อาจเป็นองค์ประกอบในหน่วยความจำที่แยกออกจาก DOM และอาจมีองค์ประกอบที่มีตัวเลือกที่ตรงกันใน DOM คนที่กำลังหาคำตอบสำหรับคำถามนี้อาจต้องการตรวจสอบว่าอยู่ใน DOM หรือไม่ มีคนทำงานในสิ่งที่รู้วิธีสืบค้น DOM อย่างชัดเจน
TJ

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