จะลบเฉพาะองค์ประกอบหลักไม่ใช่องค์ประกอบลูกใน JavaScript ได้อย่างไร


90

สมมติว่า:

<div>
  pre text
  <div class="remove-just-this">
    <p>child foo</p>
    <p>child bar</p>
    nested text
  </div>
  post text
</div>

สำหรับสิ่งนี้:

<div>
  pre text
  <p>child foo</p>
  <p>child bar</p>
  nested text
  post text
</div>

ฉันคิดหาวิธีใช้ Mootools, jQuery และแม้กระทั่ง (ดิบ) แต่ไม่เข้าใจว่าจะทำอย่างไร

คำตอบ:


139

การใช้jQueryคุณสามารถทำได้:

var cnt = $(".remove-just-this").contents();
$(".remove-just-this").replaceWith(cnt);

ลิงค์ด่วนไปยังเอกสารประกอบ:


หวังว่าฉันจะตระหนัก (err .. พบ ) เมื่อ 3 ชั่วโมงที่แล้ว ... เรียบง่ายและสง่างาม - น่ากลัว!
Tathagata

3
ความสำคัญของ 'cnt' คืออะไร?
Steven Lu

1
'cnt' เป็นเพียงชื่อตัวแปรที่มี "เนื้อหา"
George Anderson

1
ฉันไม่แน่ใจว่าทำไม แต่สิ่งนี้ไม่ได้ผลสำหรับฉันเมื่อใช้เนื้อหา () อย่างไรก็ตามเมื่อฉันใช้ html () แทนเนื้อหา () มันใช้งานได้อย่างมีเสน่ห์!
vertigoelectric

เวอร์ชัน 1 บรรทัดเท่านั้น:$('.remove-just-this').replaceWith(function() { return $(this).html(); });
Taufik Nur Rahmanda

36

วิธีการไม่ขึ้นกับไลบรารีคือการแทรกโหนดชายน์ทั้งหมดขององค์ประกอบที่จะลบก่อนตัวมันเอง (ซึ่งโดยปริยายจะลบออกจากตำแหน่งเดิม) ก่อนที่คุณจะลบออก:

while (nodeToBeRemoved.firstChild)
{
    nodeToBeRemoved.parentNode.insertBefore(nodeToBeRemoved.firstChild,
                                            nodeToBeRemoved);
}

nodeToBeRemoved.parentNode.removeChild(nodeToBeRemoved);

การดำเนินการนี้จะย้ายโหนดลูกทั้งหมดไปยังตำแหน่งที่ถูกต้องตามลำดับที่ถูกต้อง


3
Modern JS รองรับสิ่งนี้:node.replaceWith(...node.childNodes);
Gibolt

34

คุณควรตรวจสอบให้แน่ใจว่าได้ดำเนินการกับ DOM ไม่ใช่innerHTML(และหากใช้โซลูชัน jQuery ที่จัดทำโดย jk ตรวจสอบให้แน่ใจว่าได้ย้ายโหนด DOM แทนที่จะใช้innerHTMLภายใน) เพื่อรักษาสิ่งต่างๆเช่นตัวจัดการเหตุการณ์

คำตอบของฉันเหมือนกับ insin แต่จะทำงานได้ดีกว่าสำหรับโครงสร้างขนาดใหญ่ (การต่อท้ายแต่ละโหนดแยกกันอาจเป็นการเก็บภาษีในการวาดใหม่ซึ่งต้องนำ CSS มาใช้ใหม่สำหรับแต่ละรายการappendChildโดย a สิ่งDocumentFragmentนี้จะเกิดขึ้นเพียงครั้งเดียวเนื่องจากไม่สามารถมองเห็นได้จนกว่าจะถึงหลังจากนั้น เด็กทั้งหมดจะถูกต่อท้ายและเพิ่มลงในเอกสาร)

var fragment = document.createDocumentFragment();
while(element.firstChild) {
    fragment.appendChild(element.firstChild);
}
element.parentNode.replaceChild(fragment, element);

ขอขอบคุณ; สั้นและตรง
brunoais



9

ใช้ JS สมัยใหม่!

const node = document.getElementsByClassName('.remove-just-this')[0];
node.replaceWith(...node.childNodes); // or node.children, if you don't want textNodes

oldNode.replaceWith(newNode) เป็น ES5 ที่ถูกต้อง

...array เป็นตัวดำเนินการกระจายโดยส่งผ่านองค์ประกอบอาร์เรย์แต่ละรายการเป็นพารามิเตอร์


2

ไม่ว่าคุณจะใช้ไลบรารีใดคุณต้องโคลน div ภายในก่อนที่จะลบ div ภายนอกออกจาก DOM จากนั้นคุณต้องเพิ่ม div ชั้นในที่โคลนลงในตำแหน่งใน DOM ซึ่ง div ชั้นนอกอยู่ ดังนั้นขั้นตอนคือ:

  1. บันทึกการอ้างอิงถึงพาเรนต์ div ภายนอกในตัวแปร
  2. คัดลอก div ภายในไปยังตัวแปรอื่น สิ่งนี้สามารถทำได้อย่างรวดเร็วและสกปรกโดยการบันทึกinnerHTMLdiv ภายในเป็นตัวแปรหรือคุณสามารถคัดลอกโครงสร้างภายในโหนดแบบวนซ้ำทีละโหนด
  3. เรียกพาเรนต์removeChildของ div ภายนอกโดยให้ div ชั้นนอกเป็นอาร์กิวเมนต์
  4. แทรกเนื้อหาด้านในที่คัดลอกไปยังพาเรนต์ div ด้านนอกในตำแหน่งที่ถูกต้อง

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


2

และเนื่องจากคุณลองใช้ mootools เช่นกันนี่คือวิธีแก้ปัญหาใน mootools

var children = $('remove-just-this').getChildren();
children.replaces($('remove-just-this');

โปรดทราบว่ายังไม่ได้ทดสอบโดยสิ้นเชิง แต่ฉันเคยทำงานกับ mootools มาก่อนและควรใช้งานได้

http://mootools.net/docs/Element/Element#Element:getChildren

http://mootools.net/docs/Element/Element#Element:replaces



0

หากคุณต้องการทำสิ่งเดียวกันนี้ในชุดนอนนี่คือวิธีการทำ มันใช้งานได้ดี (ขอบคุณที่เปลือกตา) ฉันสามารถสร้างโปรแกรมแก้ไข Rich Text ที่เหมาะสมซึ่งสร้างสไตล์ได้อย่างเหมาะสมโดยไม่ทำให้สับสนด้วยสิ่งนี้

def remove_node(doc, element):
    """ removes a specific node, adding its children in its place
    """
    fragment = doc.createDocumentFragment()
    while element.firstChild:
        fragment.appendChild(element.firstChild)

    parent = element.parentNode
    parent.insertBefore(fragment, element)
    parent.removeChild(element)

1
ภาษานี้คือภาษาใด
brunoais

ดูเหมือนว่างูหลาม - pyjamasที่ทำให้รู้สึกตั้งแต่ผู้ใช้กล่าวถึง
mgilson

0

ฉันกำลังมองหาคำตอบที่มีประสิทธิภาพสูงสุดในขณะที่ทำงานกับ DOM ที่สำคัญ

คำตอบของการไม่มีเปลือกตาชี้ให้เห็นว่าการใช้จาวาสคริปต์จะดีที่สุด

ฉันได้ทำการทดสอบเวลาดำเนินการต่อไปนี้ใน 5,000 บรรทัดและ 400,000 ตัวอักษรโดยมีองค์ประกอบ DOM ที่ซับซ้อนภายในส่วนที่จะลบ ฉันใช้ ID แทนคลาสเพื่อความสะดวกในการใช้จาวาสคริปต์

ใช้ $ .unwrap ()

$('#remove-just-this').contents().unwrap();

201.237 มิลลิวินาที

ใช้ $ .replaceWith ()

var cnt = $("#remove-just-this").contents();
$("#remove-just-this").replaceWith(cnt);

156.983 มิลลิวินาที

การใช้ DocumentFragment ใน javascript

var element = document.getElementById('remove-just-this');
var fragment = document.createDocumentFragment();
while(element.firstChild) {
    fragment.appendChild(element.firstChild);
}
element.parentNode.replaceChild(fragment, element);

147.211 มิลลิวินาที

สรุป

ประสิทธิภาพที่ชาญฉลาดแม้ในโครงสร้าง DOM ที่ค่อนข้างใหญ่ความแตกต่างระหว่างการใช้ jQuery และ javascript นั้นไม่มาก น่าแปลกที่เป็นค่าใช้จ่ายมากที่สุดกว่า$.unwrap() $.replaceWith()ทำการทดสอบด้วย jQuery 1.12.4


0

หากคุณกำลังจัดการกับหลายแถวเหมือนในกรณีการใช้งานของฉันคุณน่าจะดีกว่ากับบางสิ่งในบรรทัดเหล่านี้:

 $(".card_row").each(function(){
        var cnt = $(this).contents();
        $(this).replaceWith(cnt);
    });
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.