[javascript] JavaScript에서 DOM 노드의 모든 하위 요소 제거

JavaScript에서 DOM 노드의 모든 하위 요소를 제거하는 방법은 무엇입니까?

다음과 같은 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이되고 싶다. DOM 전용 답변과 함께 jQuery에 답변을 제공하면 추가 포인트가 있습니다.



답변

옵션 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컴퓨터 과학과 같이 사용하도록 업데이트되었지만 일반적 으로 컬렉션 의 마지막 요소 를 제거하는 것보다 컬렉션 의 마지막 요소 를 제거하는 것이 훨씬 빠릅니다 (컬렉션 구현 방법에 따라 다름) ).
  • 루프는 (예를 들어 요소 목록이 UA에 의해 직접 연결 목록으로 구현 된 경우) 보다 확인이 더 빠를 firstChild 경우를 대비 하여 계속 확인합니다 .firstChildlastChild
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원숭이 패치 :

  • ElementJavaScript 의 프로토 타입에 새로운 메소드 속성을 추가하여 HTML 요소 객체 가 있는el.clearChildren() 곳 으로 간단하게 호출 할 수 있습니다 .el
  • 엄밀히 말하면 이것은 표준 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>


답변

innerHTMLm93a가 올바르게 언급했듯이 현재 허용되는 답변은 (IE 및 Chrome에서는) 느리다 는 점에서 잘못 되었습니다.

이 방법을 사용하면 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();

언급 된 다른 메소드는 비교 가능한 것처럼 보이지만 이상치 jquery (1.1.1 및 3.1.1)를 제외하고 innerHTML보다 훨씬 느립니다. 이는 다른 것보다 상당히 느립니다.

$(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의 “테스트 별 루프”는 종종 “반복마다”로 이해되며 첫 번째 반복 만 제거 할 노드가 있으므로 결과가 의미가 없습니다. 게시시이 스레드의 테스트가 잘못 설정되었습니다.


답변

최신 자바 스크립트를 remove!

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

이것은 ES5에서 노드 제거를 쓰는 새로운 방법입니다. 바닐라 JS이며 이전 버전보다 훨씬 잘 읽습니다 .

대부분의 사용자는 최신 브라우저를 가지고 있거나 필요한 경우 변환 할 수 있습니다.

브라우저 지원 -2019 년 12 월 95 %


답변

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

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

당신이 jQuery를이 자손에 영향이있을 가능성이 있다면, 당신은 해야한다 jQuery를 데이터를 정리하는 몇 가지 방법을 사용합니다.

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

jQuery .empty()메소드 는 제거중인 요소와 관련된 jQuery가 정리되도록합니다.

단순히 DOM자식을 제거하는 방법을 사용하면 해당 데이터가 유지됩니다.


답변

jQuery를 사용하는 경우 :

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

그렇지 않은 경우 :

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


답변

가장 빠른…

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

jsperf.com에 대한 링크 를 제공 한 Andrey Lushnikov에게 감사합니다. (쿨 사이트!) .

편집 : 명확하게 말하면 Chrome에서 firstChild와 lastChild 사이의 성능 차이는 없습니다. 가장 좋은 대답은 성능에 대한 좋은 솔루션을 보여줍니다.


답변

자식이없는 노드 만 갖고 싶다면 다음과 같이 복사본을 만들 수도 있습니다.

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

달성하려는 대상에 따라 다릅니다.