JavaScript DOM loại bỏ phần tử


198

Tôi đang cố kiểm tra xem một phần tử DOM có tồn tại hay không và nếu nó tồn tại, hãy xóa nó và nếu nó không tồn tại, hãy tạo nó.

var duskdawnkey = localStorage["duskdawnkey"];
var iframe = document.createElement("iframe");
var whereto = document.getElementById("debug");
var frameid = document.getElementById("injected_frame");
iframe.setAttribute("id", "injected_frame");
iframe.setAttribute("src", 'http://google.com');
iframe.setAttribute("width", "100%");
iframe.setAttribute("height", "400");

if (frameid) // check and see if iframe is already on page
{ //yes? Remove iframe
    iframe.removeChild(frameid.childNodes[0]);
} else // no? Inject iframe
{
    whereto.appendChild(iframe);
    // add the newly created element and it's content into the DOM
    my_div = document.getElementById("debug");
    document.body.insertBefore(iframe, my_div);
}

Kiểm tra nếu nó tồn tại hoạt động, tạo phần tử hoạt động, nhưng xóa phần tử không. Về cơ bản, tất cả các mã này là tiêm iframe vào trang web bằng cách nhấp vào nút. Điều tôi muốn xảy ra là nếu iframe đã có sẵn để xóa nó. Nhưng vì một số lý do tôi thất bại.


bản sao có thể có của JavaScript: xóa phần tử theo id
Zaz

Câu trả lời:


338

removeChild nên được gọi trên cha mẹ, tức là:

parent.removeChild(child);

Trong ví dụ của bạn, bạn nên làm một cái gì đó như:

if (frameid) {
    frameid.parentNode.removeChild(frameid);
}

Cảm ơn đã tìm ra nó ngay trước khi tôi đọc bài viết của bạn. Phải thay đổi nó thành whereeto.removeChild (whereeto.childNodes [0]);
Joshua Redfield

6
Điều đó cũng sẽ có tác dụng khi giả định rằng khung hình của bạn luôn là con đầu tiên của debugdiv. Sử dụng parentNodelà một giải pháp chung hơn sẽ làm việc với bất kỳ yếu tố nào.
casifer

1
Giải pháp này có thể không đủ. Nếu bất cứ ai đang đọc điều này, xin hãy xem gợi ý của Glenn
Sebas

79

Trong hầu hết các trình duyệt, có một cách ngắn gọn hơn một chút để loại bỏ một phần tử khỏi DOM so với cách gọi .removeChild(element)cha mẹ của nó, đó là chỉ gọi element.remove(). Theo đúng tiến trình, điều này có thể sẽ trở thành cách tiêu chuẩn và thành ngữ để loại bỏ một phần tử khỏi DOM.

Các .remove()phương pháp đã được thêm vào mức sống DOM trong năm 2011 ( cam kết ), và từ đó đã được thực hiện bởi Chrome, Firefox, Safari, Opera, và Edge. Nó không được hỗ trợ trong bất kỳ phiên bản nào của Internet Explorer.

Nếu bạn muốn hỗ trợ các trình duyệt cũ hơn, bạn sẽ cần phải bắt chước nó. Điều này hóa ra hơi khó chịu, bởi vì dường như không ai đã tạo ra một shim DOM đa năng có chứa các phương thức này và bởi vì chúng tôi không chỉ thêm phương thức vào một nguyên mẫu duy nhất; đó là một phương thức ChildNode, chỉ là một giao diện được xác định bởi thông số kỹ thuật và không thể truy cập được bằng JavaScript, vì vậy chúng tôi không thể thêm bất cứ điều gì vào nguyên mẫu của nó. Vì vậy, chúng ta cần tìm tất cả các nguyên mẫu kế thừa ChildNodevà thực sự được xác định trong trình duyệt và thêm .removechúng vào.

Đây là shim tôi đã đưa ra, mà tôi đã xác nhận hoạt động trong IE 8.

(function () {
    var typesToPatch = ['DocumentType', 'Element', 'CharacterData'],
        remove = function () {
            // The check here seems pointless, since we're not adding this
            // method to the prototypes of any any elements that CAN be the
            // root of the DOM. However, it's required by spec (see point 1 of
            // https://dom.spec.whatwg.org/#dom-childnode-remove) and would
            // theoretically make a difference if somebody .apply()ed this
            // method to the DOM's root node, so let's roll with it.
            if (this.parentNode != null) {
                this.parentNode.removeChild(this);
            }
        };

    for (var i=0; i<typesToPatch.length; i++) {
        var type = typesToPatch[i];
        if (window[type] && !window[type].prototype.remove) {
            window[type].prototype.remove = remove;
        }
    }
})();

Điều này sẽ không hoạt động trong IE 7 hoặc thấp hơn, vì việc mở rộng các nguyên mẫu DOM không thể thực hiện được trước IE 8 . Mặc dù vậy, tôi nghĩ rằng vào năm 2015, hầu hết mọi người không cần quan tâm đến những điều như vậy.

Khi bạn đã bao gồm chúng, bạn sẽ có thể xóa phần tử DOM elementkhỏi DOM bằng cách gọi

element.remove();

1
Chỉ cần để lại ở đây: polyfill.io/v2/docs/features/#Euity_prototype_remove nếu bạn bao gồm dịch vụ polyfill tự động đó, bạn sẽ nhận được hỗ trợ trở lại IE 7.
tuân thủ

4
Đây chắc chắn là cách để làm điều đó trong năm 2017 miễn là bạn không quan tâm đến IE. Xem: developer.mozilla.org/en-US/docs/Web/API/ChildNode/remove
nevf

45

Có vẻ như tôi không có đủ đại diện để đăng bình luận, vì vậy một câu trả lời khác sẽ phải làm.

Khi bạn hủy liên kết một nút bằng removeChild () hoặc bằng cách đặt thuộc tính InternalHTML trên cha, bạn cũng cần đảm bảo rằng không có gì khác tham chiếu đến nó nếu không nó sẽ không thực sự bị phá hủy và sẽ dẫn đến rò rỉ bộ nhớ. Có rất nhiều cách mà bạn có thể đã tham chiếu đến nút trước khi gọi removeChild () và bạn phải đảm bảo rằng các tham chiếu không nằm ngoài phạm vi được loại bỏ rõ ràng.

Doug Crockford viết ở đây rằng các trình xử lý sự kiện được biết là nguyên nhân của các tham chiếu vòng tròn trong IE và đề nghị xóa chúng một cách rõ ràng như sau trước khi gọi removeChild ()

function purge(d) {
    var a = d.attributes, i, l, n;
    if (a) {
        for (i = a.length - 1; i >= 0; i -= 1) {
            n = a[i].name;
            if (typeof d[n] === 'function') {
                d[n] = null;
            }
        }
    }
    a = d.childNodes;
    if (a) {
        l = a.length;
        for (i = 0; i < l; i += 1) {
            purge(d.childNodes[i]);
        }
    }
}

Và ngay cả khi bạn thực hiện nhiều biện pháp phòng ngừa, bạn vẫn có thể bị rò rỉ bộ nhớ trong IE như được mô tả bởi Jens-Ingo Farley tại đây .

Và cuối cùng, đừng rơi vào cái bẫy nghĩ rằng xóa Javascript là câu trả lời. Nó dường như được đề xuất bởi nhiều người, nhưng sẽ không thực hiện công việc. Đây là một tài liệu tham khảo tuyệt vời về sự hiểu biết xóa bởi Kangax.


1
có lẽ bạn có thể hiển thị một số jsFiddle để chứng minh điều này. Cảm ơn
Muhaimin

1
Tôi xác nhận hành vi này. Khung công tác của tôi sử dụng cây ánh xạ đối tượng Javascript trên bố cục dom. Mỗi đối tượng js tham chiếu phần tử dom của nó. Mặc dù tôi gọi element.parentNode.removeChildđể loại bỏ các yếu tố, chúng vẫn tồn tại và vẫn có thể được tham chiếu. Chúng chỉ không thể nhìn thấy trong cây dom thông thường.
Sebas

Có, và sau đó loại bỏ con trỏ toàn cục đến đối tượng ánh xạ js đó để mở khóa bộ thu gom rác một cách kỳ diệu. Đây là một bổ sung quan trọng cho câu trả lời được chấp nhận.
Sebas

11

Sử dụng Node.removeChild () thực hiện công việc cho bạn, chỉ cần sử dụng một cái gì đó như thế này:

var leftSection = document.getElementById('left-section');
leftSection.parentNode.removeChild(leftSection);

Trong DOM 4, phương thức loại bỏ được áp dụng, nhưng có hỗ trợ trình duyệt kém theo W3C:

Phương thức node.remove () được triển khai trong đặc tả DOM 4. Nhưng vì hỗ trợ trình duyệt kém, bạn không nên sử dụng nó.

Nhưng bạn có thể sử dụng phương thức remove nếu bạn sử dụng jQuery ...

$('#left-section').remove(); //using remove method in jQuery

Ngoài ra, trong các khung mới như bạn có thể sử dụng các điều kiện để loại bỏ một phần tử, ví dụ như *ngIftrong Angular và trong React, hiển thị các chế độ xem khác nhau, tùy thuộc vào các điều kiện ...


Nếu bạn đang tạo nút phương thức trong js bằng cách sử dụng createE bổ sung, thì chỉ cần đảm bảo kiểm tra xem nút có tồn tại trước khi gỡ bỏ nó không. if (leftSection) {.. mã của bạn} sẽ thực hiện công việc.
Afsan Abdulali Gujarati

0

Nếu bạn hài lòng khi sử dụng chức năng tuyệt vời:

$("#foo").remove();

Để xóa hoàn toàn thành phần khỏi DOM.

Để xóa các thành phần mà không xóa dữ liệu và sự kiện, hãy sử dụng thay thế:

$("#foo").detach();

Tài liệu jQuery

Các .remove()phương pháp có yếu tố ra khỏi DOM. Sử dụng .remove()khi bạn muốn loại bỏ phần tử chính nó, cũng như mọi thứ bên trong nó. Ngoài các phần tử, tất cả các sự kiện bị ràng buộc và dữ liệu jQuery liên quan đến các phần tử được loại bỏ. Để loại bỏ các yếu tố mà không xóa dữ liệu và sự kiện, sử dụng .detach()thay thế.

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.