ลบองค์ประกอบย่อยทั้งหมดของโหนด DOM ใน JavaScript


873

ฉันจะลบองค์ประกอบย่อยทั้งหมดของโหนด DOM ใน JavaScript ได้อย่างไร

สมมติว่าฉันมี HTML ต่อไปนี้ (น่าเกลียด):

<p id="foo">
    <span>hello</span>
    <div>world</div>
</p>

และฉันคว้าโหนดที่ฉันต้องการ:

var myNode = document.getElementById("foo");

ฉันจะลบลูก ๆ ของ fooที่เหลือ<p id="foo"></p>อยู่ได้อย่างไร

ฉันทำได้ไหม:

myNode.childNodes = new Array();

หรือฉันควรจะใช้การรวมกันของremoveElement?

ฉันต้องการคำตอบที่จะตรง DOM; แม้ว่าจะมีคะแนนเพิ่มหากคุณให้คำตอบเป็น jQuery พร้อมกับคำตอบเฉพาะ DOM เท่านั้น

คำตอบ:


1674

ตัวเลือกที่ 1 A: innerHTMLสำนักหักบัญชี

  • วิธีนี้ง่าย แต่อาจไม่เหมาะสำหรับแอปพลิเคชันที่มีประสิทธิภาพสูงเนื่องจากจะเรียกใช้ตัวแยกวิเคราะห์ HTML ของเบราว์เซอร์ (แม้ว่าเบราว์เซอร์อาจปรับให้เหมาะสมสำหรับกรณีที่ค่าเป็นสตริงว่าง)

doFoo.onclick = () => {
  const myNode = document.getElementById("foo");
  myNode.innerHTML = '';
}
<div id='foo' style="height: 100px; width: 100px; border: 1px solid black;">
  <span>Hello</span>
</div>
<button id='doFoo'>Remove via innerHTML</button>

ตัวเลือก 1 B: การหักล้าง textContent

  • ข้างต้น .textContentแต่การใช้งาน ตาม MDNสิ่งนี้จะเร็วกว่าinnerHTMLที่เบราว์เซอร์จะไม่เรียกใช้ตัวแยกวิเคราะห์ HTML และจะแทนที่เด็ก ๆ ทั้งหมดขององค์ประกอบด้วย#textโหนดเดียวแทน

doFoo.onclick = () => {
  const myNode = document.getElementById("foo");
  myNode.textContent = '';
}
<div id='foo' style="height: 100px; width: 100px; border: 1px solid black;">
  <span>Hello</span>
</div>
<button id='doFoo'>Remove via textContent</button>

ตัวเลือก 2 A: วนรอบเพื่อลบทุกรายการlastChild:

  • การแก้ไขคำตอบก่อนหน้านี้ที่ใช้ก่อนหน้านี้firstChildแต่สิ่งนี้ได้รับการอัปเดตเพื่อใช้lastChildเช่นเดียวกับในวิทยาศาสตร์คอมพิวเตอร์โดยทั่วไปจะเร็วกว่ามากในการลบคำตอบสุดท้ายออกองค์ประกอบของคอลเลกชันองค์ประกอบแรกออกมาอย่างรวดเร็ว )
  • การวนซ้ำยังคงตรวจสอบfirstChild ในกรณีที่การตรวจสอบเร็วfirstChildกว่าlastChild(เช่นหากรายการองค์ประกอบถูกนำไปใช้เป็นรายการเชื่อมโยงโดยตรงโดย UA)

doFoo.onclick = () => {
  const myNode = document.getElementById("foo");
  while (myNode.firstChild) {
    myNode.removeChild(myNode.lastChild);
  }
}
<div id='foo' style="height: 100px; width: 100px; border: 1px solid black;">
  <span>Hello</span>
</div>
<button id='doFoo'>Remove via lastChild-loop</button>

ตัวเลือก 2 B: การวนลูปเพื่อลบทุกอย่างlastElementChild:

  • วิธีการนี้จะเก็บรักษาที่ไม่ใช่ทั้งหมดElement(คือ#textโหนดและ<!-- comments --> ) ลูกของพาเรนต์ (แต่ไม่ใช่ลูกหลาน) - และสิ่งนี้อาจเป็นที่ต้องการในแอปพลิเคชันของคุณ (เช่นระบบการสร้างเทมเพลตบางระบบที่ใช้ข้อคิดเห็น HTML แบบอินไลน์
  • วิธีการนี้ไม่ได้ใช้จนกระทั่งปีที่ผ่านมาเนื่องจาก Internet Explorer ได้เพิ่มการรองรับlastElementChildใน IE9 เท่านั้น

doFoo.onclick = () => {
  const myNode = document.getElementById("foo");
  while (myNode.lastElementChild) {
    myNode.removeChild(myNode.lastElementChild);
  }
}
<div id='foo' style="height: 100px; width: 100px; border: 1px solid black;">
  <!-- This comment won't be removed -->
  <span>Hello <!-- This comment WILL be removed --></span>
  <!-- But this one won't. -->
</div>
<button id='doFoo'>Remove via lastElementChild-loop</button>

โบนัส: Element.clearChildrenแพทช์ลิง:

  • เราสามารถเพิ่มคุณสมบัติเมธอดใหม่ให้กับElementต้นแบบใน JavaScript เพื่อทำให้การเรียกใช้ง่ายขึ้นเพียงel.clearChildren()(ซึ่งelเป็นวัตถุองค์ประกอบ HTML ใด ๆ )
  • (การพูดอย่างเคร่งครัดนี่คือ Monkey-patch ไม่ใช่ polyfill เนื่องจากนี่ไม่ใช่คุณสมบัติ DOM มาตรฐานหรือคุณสมบัติที่ขาดหายไปโปรดทราบว่าการแก้ไขโดยลิงนั้นไม่ได้รับอนุญาตอย่างถูกต้องในหลาย ๆ สถานการณ์)

if( typeof Element.prototype.clearChildren === 'undefined' ) {
    Object.defineProperty(Element.prototype, 'clearChildren', {
      configurable: true,
      enumerable: false,
      value: function() {
        while(this.firstChild) this.removeChild(this.lastChild);
      }
    });
}
<div id='foo' style="height: 100px; width: 100px; border: 1px solid black;">
  <span>Hello <!-- This comment WILL be removed --></span>
</div>
<button onclick="this.previousElementSibling.clearChildren()">Remove via monkey-patch</button>


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

104
Btw การใช้ lastChild ดูเหมือนจะมีประสิทธิภาพมากกว่าjsperf.com/innerhtml-vs-removechild/15
Andrey Lushnikov

24
innerHTML ใช้งานได้เฉพาะถ้าคุณจัดการกับ HTML เท่านั้น หากมีเช่น SVG ภายในการลบองค์ประกอบเท่านั้นจะใช้งานได้
stwissel

34
ไม่เคยไม่เคยใช้ innerHTML = '' อย่า ปัญหาคือว่ารายการดูเหมือนว่าพวกเขาจะถูกลบ แต่ภายในโหนดยังคงอยู่และช้าลง คุณต้องลบแต่ละโหนดทั้งหมดเพื่อเหตุผล ผ่านการทดสอบทั้งใน Google Chrome และ IE โปรดลองลบ "แก้ปัญหา" innerHTML เนื่องจากมันผิด
เคนจิ

15
@vsync ฉันไม่เชื่อว่าความคิดเห็นของเคนจินั้นดีขึ้น การทำinnerHTML = ''ช้าลง แต่ฉันไม่คิดว่ามัน "ผิด" การเรียกร้องใด ๆ ของการรั่วไหลของหน่วยความจำควรสำรองด้วยหลักฐาน
Chris Middleton

115

คำตอบที่ยอมรับในปัจจุบันนั้นผิดเกี่ยวกับinnerHTMLการช้าลง (อย่างน้อยใน IE และ Chrome) ตามที่ m93a กล่าวถึงอย่างถูกต้อง

Chrome และ FF เร็วขึ้นอย่างมากโดยใช้วิธีนี้ (ซึ่งจะทำลายข้อมูล jquery ที่แนบมา):

var cNode = node.cloneNode(false);
node.parentNode.replaceChild(cNode, node);

ในอีกไม่กี่วินาทีสำหรับ FF และ Chrome และเร็วที่สุดใน IE:

node.innerHTML = '';

InnerHTML จะไม่ทำลายตัวจัดการเหตุการณ์ของคุณหรือทำลายอ้างอิง jQueryก็ยังแนะนำเป็นวิธีแก้ปัญหาที่นี่: https://developer.mozilla.org/en-US/docs/Web/API/Element.innerHTML

วิธีการจัดการ DOM ที่เร็วที่สุด (ยังช้ากว่าสองรายการก่อนหน้า) คือการลบช่วง แต่ไม่รองรับช่วงจนถึง IE9

var range = document.createRange();
range.selectNodeContents(node);
range.deleteContents();

วิธีอื่น ๆ ที่กล่าวมาดูเหมือนจะเปรียบเทียบกัน แต่ช้ากว่า innerHTML มากยกเว้น outquery, jquery (1.1.1 และ 3.1.1) ซึ่งช้ากว่าสิ่งอื่นมาก:

$(node).empty();

หลักฐานที่นี่:

http://jsperf.com/innerhtml-vs-removechild/167 http://jsperf.com/innerhtml-vs-removechild/300 https://jsperf.com/remove-all-child-elements-of-a- dom-node-in-javascript (URL ใหม่สำหรับ jsperf รีบูตเนื่องจากการแก้ไข URL เก่าไม่ทำงาน)

"ต่อการทดสอบลูป" ของ Jsperf มักจะถูกเข้าใจว่าเป็น "การทำซ้ำต่อ" และเฉพาะการทำซ้ำครั้งแรกเท่านั้นที่มีโหนดที่จะลบดังนั้นผลลัพธ์จึงไม่มีความหมายในขณะที่ทำการโพสต์มีการทดสอบในชุดข้อความนี้


2
jsperf ของคุณเสียอย่างสมบูรณ์ นั่นไม่ใช่หลักฐานที่ดีมาก
bryc

4
นี่คือคำตอบที่ดีที่สุดในปัจจุบัน ทุกอย่างอื่นในหัวข้อนี้เป็นการบิดเบือนข้อมูล (!) ขอขอบคุณที่ทำความสะอาดการทดสอบเก่า ๆ ที่ไม่ดีทั้งหมด
Ben

6
"InnerHTML จะไม่ทำลายตัวจัดการเหตุการณ์ของคุณหรือทำให้การอ้างอิง jQuery ยุ่งเหยิง"มันจะทำให้ข้อมูลเด็กกำพร้าjQuery.cacheทำให้หน่วยความจำรั่วเพราะการอ้างอิงเดียวที่มีอยู่เพื่อจัดการข้อมูลนั้นอยู่ในองค์ประกอบที่คุณเพิ่งทำลาย

1
"InnerHTML จะไม่ทำลายตัวจัดการเหตุการณ์ของคุณหรือทำให้การอ้างอิง jquery ใด ๆ " หมายถึงคอนเทนเนอร์ไม่ใช่ลูก ๆ cloneNodeเปลี่ยนภาชนะซึ่งหมายความว่าการอ้างอิงไปยังภาชนะบรรจุจะไม่ได้รับการดูแล (jquery หรืออย่างอื่น) แคชของ Jquery อาจทำให้คุ้มค่าโดยใช้ jquery เพื่อลบองค์ประกอบหากคุณมี jquery data ติดอยู่ หวังว่าพวกเขาจะเปลี่ยนเป็นWeakMapsในบางจุด การล้าง (หรือแม้กระทั่งการมีอยู่) $ .cache จะไม่ปรากฏเป็นเอกสารอย่างเป็นทางการ
npjohns

10
การทดสอบ jsperf แตกที่นี่ เอ็นจิ้นทดสอบรายงานต่อไปนี้: "ข้อผิดพลาด: โหนด Dom ไม่ได้ถูกสร้างขึ้นใหม่ในระหว่างการทำซ้ำผลการทดสอบจะไม่มีความหมาย"
senderle

73

ใช้ Javascript ที่ทันสมัยด้วยremove!

const parent = document.getElementById("foo");
while (parent.firstChild) {
    parent.firstChild.remove();
}

นี่เป็นวิธีใหม่ในการเขียนการลบโหนดใน ES5 มันคือวานิลลา JS และอ่านได้ดีกว่ารุ่นก่อนหน้ามาก

ผู้ใช้ส่วนใหญ่ควรมีเบราว์เซอร์ที่ทันสมัยหรือคุณสามารถ transpile หากจำเป็น

รองรับเบราว์เซอร์ - 95% ธันวาคม 2019


14
for for loop จะไม่ทำงานเนื่องจาก parent.children / parent.childNodes เป็นรายการสด การเรียกลบจะปรับเปลี่ยนรายการและตัววนซ้ำของคุณจึงไม่รับประกันว่าจะวนซ้ำทุกสิ่ง ใน Chrome เช่นคุณสิ้นสุดการข้ามโหนดอื่น ๆ ดีกว่าที่จะใช้while (parent.firstChild) { parent.removeChild(parent.firstChild); }วง developer.mozilla.org/en-US/docs/Web/API/ParentNode/children developer.mozilla.org/en-US/docs/Web/API/Node/childNodes
qix

3
จดชวเลขแม้ว่าจะอ่านน้อยกว่า:while (parent.firstChild && !parent.firstChild.remove());
Gibolt

1
หนึ่งซับในเมื่อประสิทธิภาพไม่ได้เป็นเรื่องใหญ่:[...parent.childNodes].forEach(el => el.remove());

1
สิ่งนี้ไม่ทำงานใน typescript ... แทนที่จะใช้while (selectElem.firstElementChild) { selectElem.firstElementChild.remove(); }
John Henckel

43
var myNode = document.getElementById("foo");
var fc = myNode.firstChild;

while( fc ) {
    myNode.removeChild( fc );
    fc = myNode.firstChild;
}

หากมีโอกาสที่คุณจะได้รับผลกระทบจากการสืบทอด jQuery คุณต้องใช้วิธีการที่จะล้างข้อมูล jQuery

$('#foo').empty();

.empty()วิธีการjQueryจะทำให้มั่นใจได้ว่าข้อมูลใด ๆ ที่ jQuery ที่เกี่ยวข้องกับองค์ประกอบที่ถูกลบจะถูกล้างออก

หากคุณใช้DOMวิธีลบเด็ก ๆ ข้อมูลนั้นจะยังคงอยู่


วิธี innerHTML นั้นเป็นวิธีที่มีประสิทธิภาพมากที่สุด ที่กล่าวไว้ว่าข้อมูลกำลังถูกล้างข้อมูลโดย .empty () ของ jquery: กำจัดข้อมูล () ภายใน jquery ที่เกี่ยวข้องกับแท็กลูกโดยใช้วนซ้ำ (ช้า แต่อาจลดการใช้หน่วยความจำอย่างมีนัยสำคัญ) ป้องกันการรั่วไหลของหน่วยความจำ jquery เช่นใช้. onclick = ... หากคุณไม่มีกิจกรรมดังกล่าวในเด็ก ๆ ที่จะลบการตั้งค่า innerHTML จะไม่รั่วไหล ดังนั้นคำตอบที่ดีที่สุดคือ - มันขึ้นอยู่กับ
Chris Moschini

1
ทำไมไม่เพียงใส่นิพจน์แรกของเด็กลงในเงื่อนไขของลูป while โดยตรง while ( myNode.firstChild ) {
Victor Zamanian

while(fc = myNode.firstChild){ myNode.removeChild(fc); }
Valen

36

หากคุณใช้ jQuery:

$('#foo').empty();

หากคุณไม่:

var foo = document.getElementById('foo');
while (foo.firstChild) foo.removeChild(foo.firstChild);

20

ที่เร็วที่สุด...

var removeChilds = function (node) {
    var last;
    while (last = node.lastChild) node.removeChild(last);
};

ขอบคุณ Andrey Lushnikov สำหรับลิงก์ของเขาไปยัง jsperf.com (เว็บไซต์ยอดเยี่ยม!)

แก้ไข: เพื่อให้ชัดเจนไม่มีความแตกต่างด้านประสิทธิภาพใน Chrome ระหว่าง firstChild และ lastChild คำตอบยอดนิยมแสดงให้เห็นถึงทางออกที่ดีสำหรับประสิทธิภาพ


สิ่งเดียวกันโดยไม่มีคำเตือน LINT: clear: function (container) {for (;;) {var child = container.lastChild; ถ้า (! เด็ก) หยุด; container.removeChild (เด็ก); }}
cskwg

9

หากคุณต้องการมีโหนดที่ไม่มีโหนดลูกคุณก็สามารถทำสำเนาได้เช่นนี้

var dupNode = document.getElementById("foo").cloneNode(false);

ขึ้นอยู่กับสิ่งที่คุณพยายามทำ


3
บางทีคุณอาจจะทำตามสิ่งนี้ด้วยparent.replaceChild(cloned, original)? นั่นอาจเร็วกว่าการลบเด็กทีละคนและควรทำงานกับทุกสิ่งที่รองรับ DOM (ดังนั้นเอกสาร XML ทุกประเภทรวมถึง SVG) การตั้งค่า innerHTML อาจเร็วกว่าการลบเด็กทีละคน แต่นั่นไม่สามารถทำงานได้กับทุกอย่างยกเว้นเอกสาร HTML ควรทดสอบว่าบางครั้ง
Maarten

13
addEventListenerที่จะไม่คัดลอกฟังเหตุการณ์เพิ่มการใช้
แมทธิว

หากคุณสามารถอยู่กับข้อ จำกัด นั้นได้อย่างรวดเร็วแน่นอน: jsperf.com/innerhtml-vs-removechild/137
DanMan

7

นี่เป็นวิธีการอื่น:

function removeAllChildren(theParent){

    // Create the Range object
    var rangeObj = new Range();

    // Select all of theParent's children
    rangeObj.selectNodeContents(theParent);

    // Delete everything that is selected
    rangeObj.deleteContents();
}

1
สิ่งนี้น่าสนใจ แต่มันค่อนข้างช้าเมื่อเทียบกับวิธีอื่น ๆ : jsperf.com/innerhtml-vs-removechild/256
Polaris878

6
element.textContent = '';

มันเหมือน innerText ยกเว้นมาตรฐาน มันช้ากว่านิดหน่อยremoveChild()แต่มันใช้งานง่ายกว่าและจะไม่สร้างความแตกต่างด้านประสิทธิภาพมากนักหากคุณไม่มีสิ่งที่จะลบมากเกินไป


โหนดข้อความไม่ใช่องค์ประกอบ
check_ca

ขอโทษที่คุณพูดถูกเอาองค์ประกอบของเด็ก ๆ ออกไปอย่างแน่นอน
check_ca

สิ่งนี้จะไม่ทำงานใน Internet Explorer เวอร์ชันเก่า
pwdst

4

ในการตอบสนองต่อ DanMan, Maarten และ Matt การโคลนโหนดเพื่อตั้งค่าข้อความเป็นวิธีที่ทำงานได้จริงในผลลัพธ์ของฉัน

// @param {node} node
// @return {node} empty node
function removeAllChildrenFromNode (node) {
  var shell;
  // do not copy the contents
  shell = node.cloneNode(false);

  if (node.parentNode) {
    node.parentNode.replaceChild(shell, node);
  }

  return shell;
}

// use as such
var myNode = document.getElementById('foo');
myNode = removeAllChildrenFromNode( myNode );

นอกจากนี้ยังใช้งานได้กับโหนดที่ไม่อยู่ใน dom ซึ่งคืนค่า null เมื่อพยายามเข้าถึง parentNode นอกจากนี้หากคุณต้องการความปลอดภัยโหนดว่างเปล่าก่อนเพิ่มเนื้อหาสิ่งนี้มีประโยชน์จริง ๆ พิจารณากรณีการใช้งานที่อยู่ด้านล่าง

// @param {node} node
// @param {string|html} content
// @return {node} node with content only
function refreshContent (node, content) {
  var shell;
  // do not copy the contents
  shell = node.cloneNode(false);

  // use innerHTML or you preffered method
  // depending on what you need
  shell.innerHTML( content );

  if (node.parentNode) {
    node.parentNode.replaceChild(shell, node);
  }

  return shell;
}

// use as such
var myNode = document.getElementById('foo');
myNode = refreshContent( myNode );

ฉันพบว่าวิธีนี้มีประโยชน์มากเมื่อแทนที่สตริงภายในองค์ประกอบถ้าคุณไม่แน่ใจว่าโหนดจะมีอะไรแทนที่จะกังวลวิธีทำความสะอาดระเบียบให้เริ่มต้นใหม่


3
สิ่งที่แย่ที่สุดที่เคยมีมา หากคุณกำลังแทนที่โหนดเดิมด้วยโคลนของมันคุณจะสูญเสียการอ้างอิงไปยังโหนดเดิม ไม่มีตัวจัดการเหตุการณ์และการโยงอื่น ๆ จะไม่ทำงาน
Arun Aravind

4

นี่คือสิ่งที่ฉันมักจะทำ:

HTMLElement.prototype.empty = function() {
    while (this.firstChild) {
        this.removeChild(this.firstChild);
    }
}

และ voila หลังจากนั้นคุณสามารถทำให้ว่างองค์ประกอบ dom ด้วย:

anyDom.empty()

ฉันชอบวิธีนี้! เหตุผลใดที่ฉันควรใช้การตั้งค่า innerHTML เป็นสตริงว่าง
TheCodenator

ประสิทธิภาพ: domEl.innerHTML = ""แย่และถือว่าเป็นการปฏิบัติที่ไม่ดี
Ado Ren

3

มีสองตัวเลือกเพื่อให้บรรลุว่า:

ที่เร็วที่สุด ():

while (node.lastChild) {
  node.removeChild(node.lastChild);
}

ทางเลือก (ช้ากว่า):

while (node.firstChild) {
  node.removeChild(node.firstChild);
}

while (node.hasChildNodes()) {
  node.removeChild(node.lastChild);
}

เกณฑ์มาตรฐานพร้อมตัวเลือกที่แนะนำ


3
var empty_element = function (element) {

    var node = element;

    while (element.hasChildNodes()) {              // selected elem has children

        if (node.hasChildNodes()) {                // current node has children
            node = node.lastChild;                 // set current node to child
        }
        else {                                     // last child found
            console.log(node.nodeName);
            node = node.parentNode;                // set node to parent
            node.removeChild(node.lastChild);      // remove last node
        }
    }
}

สิ่งนี้จะลบโหนดทั้งหมดในองค์ประกอบ


... เพราะมันซับซ้อนโดยไม่จำเป็นและไม่มีคำอธิบายว่ามันทำงานอย่างไร (ซึ่งจริงๆแล้วไม่ชัดเจน) ฉันสงสัย
Periata Breatta

2

InnerText เป็นผู้ชนะ! http://jsperf.com/innerhtml-vs-removechild/133 ในการทดสอบก่อนหน้านี้ทั้งหมด dom ภายในของโหนดหลักถูกลบในการวนซ้ำครั้งแรกจากนั้น InnerHTML หรือ removeChild โดยที่ใช้กับ div ที่ว่างเปล่า


5
innerTextเป็นสิ่ง MS ที่เป็นกรรมสิทธิ์แม้ว่า แค่พูด.
DanMan

1
ค่อนข้างแน่ใจว่านี่คือการทดสอบที่มีข้อบกพร่อง - ขึ้นอยู่กับboxว่าไม่ได้เป็น var แต่ผ่านการค้นหา DOM ตาม id และเนื่องจากการwhileวนซ้ำทำให้การโทรช้านี้หลายครั้งมันถูกลงโทษ
nrabinowitz


2

ฉันเห็นคนกำลังทำ:

while (el.firstNode) {
    el.removeChild(el.firstNode);
}

ถ้ามีคนบอกว่าใช้el.lastNodeเร็วกว่า

อย่างไรก็ตามฉันคิดว่านี่เป็นวิธีที่เร็วที่สุด:

var children = el.childNodes;
for (var i=children.length - 1; i>-1; i--) {
    el.removeNode(children[i]);
}

คุณคิดอย่างไร?

PS: หัวข้อนี้เป็นตัวช่วยชีวิตสำหรับฉัน firefox addon ของฉันถูกปฏิเสธเพราะฉันใช้ innerHTML มันเคยเป็นนิสัยมาเป็นเวลานาน ถ้าอย่างนั้นฉันก็ทำอย่างนี้ และฉันก็สังเกตเห็นความแตกต่างความเร็ว ในการโหลด Innerhtml ใช้เวลาสักครู่ในการอัปเดต แต่จะดำเนินการตาม addElement ทันที!


1
ดีฉันคิดว่าจะเร็วหรือไม่การทดสอบ jsperfบางอย่างสามารถพิสูจน์กรณีใด
Nikos M.

super work ขอบคุณสำหรับการทดสอบเหล่านั้น พวกเขาไม่ได้รวมถึงfor (var i=0...แม้ว่า แต่นี่คือสิ่งที่ฉันได้รับเมื่อฉันทำการทดสอบเหล่านั้น: i.imgur.com/Mn61AmI.pngดังนั้นในการทดสอบทั้งสามครั้งแรกโหนดเร็วกว่า lastNode และ innerHTML ซึ่งเป็นสิ่งที่ดีจริง ๆ
Noitidart

ฉันได้เพิ่มการทดสอบ: jsperf.com/innerhtml-vs-removechild/220สิ่งที่น่าสนใจที่ทำวิธี el.firstNode เป็นวิธีที่เร็วที่สุดที่ดูเหมือน
Noitidart

2

การใช้ช่วงลูปจะรู้สึกเป็นธรรมชาติที่สุดสำหรับฉัน:

for (var child of node.childNodes) {
    child.remove();
}

ตามการวัดของฉันใน Chrome และ Firefox มันช้าลงประมาณ 1.3 เท่า ในสถานการณ์ปกติสิ่งนี้อาจไม่สำคัญ


2
 let el = document.querySelector('#el');
 if (el.hasChildNodes()) {
      el.childNodes.forEach(child => el.removeChild(child));
 }

1
โปรดอธิบายคำตอบว่าโค้ดของคุณทำอะไรอยู่
Nirav Joshi

1
มันอธิบายตนเอง
blacksheep

1

โดยทั่วไป JavaScript ใช้อาร์เรย์เพื่ออ้างอิงรายการของโหนด DOM ดังนั้นสิ่งนี้จะทำงานได้ดีถ้าคุณมีความสนใจในการทำมันผ่านอาร์เรย์ HTMLElements นอกจากนี้ยังมีข้อควรระวังเนื่องจากฉันใช้การอ้างอิงอาเรย์แทน JavaScript proto สิ่งนี้ควรใช้ได้กับเบราว์เซอร์ใด ๆ รวมถึง IE

while(nodeArray.length !== 0) {
  nodeArray[0].parentNode.removeChild(nodeArray[0]);
}

1

ทำไมเราไม่ทำตามวิธีที่ง่ายที่สุดที่นี่ "ลบ" วนซ้ำภายในขณะที่

const foo = document.querySelector(".foo");
while (foo.firstChild) {
  foo.firstChild.remove();     
}
  • การเลือกผู้ปกครอง div
  • การใช้วิธี "remove" ภายในห่วงวนขณะเพื่อกำจัดองค์ประกอบลูกที่หนึ่งจนกระทั่งไม่มีสิ่งใดเหลืออยู่

โปรดอธิบายบรรทัดโค้ดของคุณเพื่อให้ผู้ใช้รายอื่นเข้าใจการทำงานของมัน ขอบคุณ!
Ignacio Ara

@IgnacioAra เรียบร้อยแล้ว!
Neelansh Verma

1

เพิ่งเห็นใครบางคนพูดถึงคำถามนี้และคิดว่าฉันจะเพิ่มวิธีการที่ฉันยังไม่เห็น:

function clear(el) {
    el.parentNode.replaceChild(el.cloneNode(false), el);
}

var myNode = document.getElementById("foo");
clear(myNode);

ฟังก์ชั่นที่ชัดเจนคือการใช้องค์ประกอบและการใช้โหนดแม่เพื่อแทนที่ตัวเองด้วยการคัดลอกโดยไม่ต้องเป็นลูก ประสิทธิภาพเพิ่มขึ้นไม่มากนักหากองค์ประกอบกระจัดกระจาย แต่เมื่อองค์ประกอบมีโหนดจำนวนมากประสิทธิภาพจะเพิ่มขึ้น


1
จริง ๆ แล้วดูเหมือนว่ามันถูกกล่าวถึงที่นี่stackoverflow.com/a/15441725/576767
Félix Gagnon-Grenier

เฟลิกซ์ฉันต้องพลาดไปแล้วขอบคุณสำหรับการแก้ไข +1
Harry Chilinguerian

1

วิธีการทำงานเฉพาะ:

const domChildren = (el) => Array.from(el.childNodes)
const domRemove = (el) => el.parentNode.removeChild(el)
const domEmpty = (el) => domChildren(el).map(domRemove)

"childNodes" ใน domChildren จะให้ nodeList ขององค์ประกอบชายด์ทันทีซึ่งว่างเปล่าเมื่อไม่พบ เพื่อแม็พผ่าน nodeList domChildren จะแปลงเป็นอาร์เรย์ domEmpty แมปฟังก์ชัน domRemove เหนือองค์ประกอบทั้งหมดที่เอาออก

ตัวอย่างการใช้งาน:

domEmpty(document.body)

ลบเด็กทั้งหมดออกจากองค์ประกอบร่างกาย


0

วิธีอื่น ๆ ใน jQuery

var foo = $("#foo");
foo.children().remove();
//or
$("*", foo ).remove();
//or
foo.html("");
//or
foo.empty();

การลงคะแนนเสียงเนื่องจาก OP กล่าวว่าต้องการคำตอบใน DOM แบบตรง
bwindels

นอกจากนี้ jQuery มี.empty()วิธีการ$("#foo").empty()ก็เพียงพอแล้ว
YakovL

-1

เพียงแค่ IE เท่านั้น:

parentElement.removeNode(true);

true - หมายถึงทำการลบอย่างลึก - ซึ่งหมายความว่าเด็กทุกคนจะถูกลบออกด้วย


1
IE? นี่คือศตวรรษที่ 21!
everlasto

-1

วิธีที่ง่ายที่สุด:

let container = document.getElementById("containerId");
container.innerHTML = "";

ในขณะที่งานนี้ระวังว่าcontainer.innerHTML = nullจะทำให้ Internet Explorer nullแสดงข้อความ ดังนั้นนี่ไม่ได้เป็นการลบเด็ก ๆ ออกไปอย่างแน่นอน
Arjan

-1

ง่ายและรวดเร็วในการใช้วนรอบ !!

var myNode = document.getElementById("foo");

    for(var i = myNode.childNodes.length - 1; i >= 0; --i) {
      myNode.removeChild(myNode.childNodes[i]);
    }

สิ่งนี้จะไม่ทำงานใน<span>แท็ก!


ในการแก้ปัญหาดังกล่าวข้างต้นทั้งหมดไม่มีรหัสเป็นลบ<span>แท็ก
Mohit Karkar

-3

หากคุณต้องการที่จะนำบางสิ่งบางอย่างกลับเข้ามาในที่divที่innerHTMLอาจจะดีกว่าคือ

ตัวอย่างของฉัน:

<ul><div id="result"></div></ul>

<script>
  function displayHTML(result){
    var movieLink = document.createElement("li");
    var t = document.createTextNode(result.Title);
    movieLink.appendChild(t);
    outputDiv.appendChild(movieLink);
  }
</script>

ถ้าฉันใช้.firstChildหรือ.lastChildวิธีการdisplayHTML()ฟังก์ชั่นไม่ทำงานหลังจากนั้น แต่ไม่มีปัญหากับ.innerHTMLวิธีการ


-4

นี่คือจาวาสคริปต์ที่แท้จริงฉันไม่ได้ใช้ jQuery แต่ใช้ได้กับเบราว์เซอร์ทั้งหมดแม้กระทั่ง IE และมันก็เข้าใจง่าย

   <div id="my_div">
    <p>Paragraph one</p>
    <p>Paragraph two</p>
    <p>Paragraph three</p>
   </div>
   <button id ="my_button>Remove nodes ?</button>

   document.getElementById("my_button").addEventListener("click",function(){

  let parent_node =document.getElemetById("my_div"); //Div which contains paagraphs

  //Let find numbers of child inside the div then remove all
  for(var i =0; i < parent_node.childNodes.length; i++) {
     //To avoid a problem which may happen if there is no childNodes[i] 
     try{
       if(parent_node.childNodes[i]){
         parent_node.removeChild(parent_node.childNodes[i]);
       }
     }catch(e){
     }
  }

})

or you may simpli do this which is a quick way to do

document.getElementById("my_button").addEventListener("click",function(){

 let parent_node =document.getElemetById("my_div");
 parent_node.innerHTML ="";

})

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