Làm cách nào để chỉ xóa phần tử mẹ chứ không phải phần tử con của nó trong JavaScript?


88

Hãy cùng nói nào:

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

đến điều này:

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

Tôi đã tìm cách sử dụng Mootools, jQuery và thậm chí là JavaScript (thô), nhưng không thể biết cách thực hiện điều này.

Câu trả lời:


138

Sử dụng jQuery bạn có thể làm điều này:

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

Liên kết nhanh đến tài liệu:


Ước gì tôi nhận ra (ờ .. tìm thấy ) điều này 3 giờ trước ... đơn giản và thanh lịch - tuyệt vời!
Như Lai

3
ý nghĩa của 'cnt' là gì?
Steven Lu

1
'cnt' chỉ là một tên biến chứa "nội dung"
George Anderson

1
Tôi không chắc tại sao, nhưng điều này không hiệu quả với tôi khi sử dụng nội dung (). Tuy nhiên, khi tôi sử dụng html () thay cho nội dung (), nó hoạt động như một sự quyến rũ!
vertigo electro,

phiên bản chỉ 1 dòng:$('.remove-just-this').replaceWith(function() { return $(this).html(); });
Taufik Nur Rahmanda

36

Phương thức không phụ thuộc vào thư viện là chèn tất cả các nút con của phần tử sẽ bị xóa trước chính nó (điều này hoàn toàn xóa chúng khỏi vị trí cũ), trước khi bạn xóa nó:

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

nodeToBeRemoved.parentNode.removeChild(nodeToBeRemoved);

Thao tác này sẽ di chuyển tất cả các nút con đến đúng vị trí theo đúng thứ tự.


3
Hiện đại JS hỗ trợ này:node.replaceWith(...node.childNodes);
Gibolt

34

Bạn nên đảm bảo thực hiện điều này với DOM chứ không phải innerHTML(và nếu sử dụng giải pháp jQuery do jk cung cấp, hãy đảm bảo rằng nó di chuyển các nút DOM thay vì sử dụng innerHTMLnội bộ), để bảo vệ những thứ như trình xử lý sự kiện.

Câu trả lời của tôi rất giống với insin, nhưng sẽ hoạt động tốt hơn đối với các cấu trúc lớn (việc nối từng nút riêng biệt có thể đánh thuế vào các bản vẽ lại nơi CSS phải được áp dụng lại cho từng nút appendChild; với a DocumentFragment, điều này chỉ xảy ra một lần vì nó không được hiển thị cho đến sau trẻ em đều được thêm vào và nó được thêm vào tài liệu).

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

Cảm ơn bạn; ngắn gọn và trực tiếp.
brunoais


22

Cách thanh lịch hơn là

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

2
Câu trả lời tốt nhất. Cảm ơn.
user706420

7

Sử dụng JS hiện đại!

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

oldNode.replaceWith(newNode) là ES5 hợp lệ

...array là toán tử lây lan, chuyển mỗi phần tử mảng dưới dạng một tham số


2

Cho dù bạn đang sử dụng thư viện nào, bạn phải sao chép div bên trong trước khi xóa div bên ngoài khỏi DOM. Sau đó, bạn phải thêm div bên trong được sao chép vào vị trí trong DOM mà div bên ngoài đã ở đó. Vì vậy, các bước là:

  1. Lưu một tham chiếu đến cha của div bên ngoài trong một biến
  2. Sao chép div bên trong sang một biến khác. Điều này có thể được thực hiện một cách nhanh chóng và dễ dàng bằng cách lưu innerHTMLdiv bên trong vào một biến hoặc bạn có thể sao chép đệ quy cây bên trong từng nút.
  3. Gọi removeChildhàm cha bên ngoài của div với đối số là div bên ngoài.
  4. Chèn nội dung đã sao chép vào bên trong div bên ngoài vào đúng vị trí.

Một số thư viện sẽ thực hiện một số hoặc tất cả điều này cho bạn nhưng một số thứ như trên sẽ diễn ra ngầm.



1

Thay thế div bằng nội dung của nó:

const wrapper = document.querySelector('.remove-just-this');
wrapper.outerHTML = wrapper.innerHTML;
<div>
  pre text
  <div class="remove-just-this">
    <p>child foo</p>
    <p>child bar</p>
    nested text
  </div>
  post text
</div>


0

nếu bạn muốn làm điều này tương tự trong bộ đồ ngủ, đây là cách thực hiện. nó hoạt động tuyệt vời (cảm ơn bạn đến mí mắt). Tôi đã có thể tạo ra một trình soạn thảo văn bản đa dạng thức phù hợp để thực hiện đúng các kiểu mà không làm rối mắt, nhờ vào điều này.

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
Đây là ngôn ngữ nào?
brunoais

Trông giống như python - điều này có ý nghĩa khi người dùng đề cập pyjamas.
mgilson

0

Tôi đang tìm kiếm câu trả lời tốt nhất về hiệu suất khi làm việc trên một DOM quan trọng.

câu trả lời của người không có mí mắt đã chỉ ra rằng sử dụng javascript thì các buổi biểu diễn sẽ là tốt nhất.

Tôi đã thực hiện các bài kiểm tra thời gian thực thi sau trên 5.000 dòng và 400.000 ký tự với thành phần DOM phức tạp bên trong phần cần xóa. Tôi đang sử dụng ID thay vì lớp vì lý do thuận tiện khi sử dụng javascript.

Sử dụng $ .unwrap ()

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

201.237ms

Sử dụng $ .replaceWith ()

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

156,983ms

Sử dụng DocumentFragment trong 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,211ms

Phần kết luận

Về hiệu suất, ngay cả trên một cấu trúc DOM tương đối lớn, sự khác biệt giữa việc sử dụng jQuery và javascript là không lớn. Đáng ngạc nhiên $.unwrap()là tốn kém nhất $.replaceWith(). Các bài kiểm tra đã được thực hiện với jQuery 1.12.4.


0

Nếu bạn đang xử lý nhiều hàng, như trong trường hợp sử dụng của tôi, bạn có thể tốt hơn với một cái gì đó dọc theo các dòng sau:

 $(".card_row").each(function(){
        var cnt = $(this).contents();
        $(this).replaceWith(cnt);
    });
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.