JavaScript를 사용하여 모든 HTML 요소 자식을 다른 부모로 이동하는 방법은 무엇입니까?


80

상상해보십시오.

<div id="old-parent">
    <span>Foo</span>
    <b>Bar</b>
    Hello World
</div>
<div id="new-parent"></div>

자바 스크립트에서 모든 자식 노드 (두 요소, 텍스트 노드)를 이동 기록 할 수있는 일 old-parentnew-parentjQuery를하지 않고?

노드 사이의 공백은 신경 쓰지 않지만 stray를 잡을 것으로 예상하지만 Hello World그대로 마이그레이션해야합니다.

편집하다

명확하게 말하면 다음과 같이 끝내고 싶습니다.

<div id="old-parent"></div>
<div id="new-parent">
    <span>Foo</span>
    <b>Bar</b>
    Hello World
</div>

이것이 제안 된 중복 인 질문에 대한 답변은 다음과 같습니다.

<div id="new-parent">
    <div id="old-parent">
        <span>Foo</span>
        <b>Bar</b>
        Hello World
    </div>
</div>


6
@MarcB, 이것은 중복이 아닙니다. 당신이 연결 문제는 이동 처리하지 않는 모든 아이들이 없으며, 그 질문에 주소 HTML 노드의 서로 다른 유형의 이동 내 필요에 어떤 답변을하지 않습니다 (예 : 텍스트 노드로합니다.)
드류 녹스

2
대답은 정확히 필요한 것입니다. 돔은 나무입니다. 한 노드를 이동하면 해당 노드의 모든 자식도 함께 이동합니다.
Marc B

@MarcB 때로는 대상에 부모 개체를 원하지 않습니다. 예를 들어 TODO 목록의 모든 요소를 ​​'보류 중'에서 '완료'상위 요소로 이동하는 것을 고려하십시오.
Drew Noakes

답변:


124

데모

기본적으로 이전 상위 노드의 각 직계 하위 항목을 반복하여 새 상위 노드로 이동하려고합니다. 직계 자손의 모든 자녀는 함께 움직입니다.

var newParent = document.getElementById('new-parent');
var oldParent = document.getElementById('old-parent');

while (oldParent.childNodes.length > 0) {
    newParent.appendChild(oldParent.childNodes[0]);
}

8
정말 효율적이 while (oldParent.childNodes.length) { newParent.appendChild(oldParent.firstChild); }
되려면

4
일반적으로 childNodes []에는 빈 텍스트 노드도 포함되어 있습니다 (소스 코드의 각 줄 바꿈마다 하나씩).
Dercsár

5
@Gibolt JSPerf 테스트를 만들었고 배열 액세스가 호출하는 것보다 빠르다는 것을 나타내는 것 같습니다 firstChild. 그 차이는 기껏해야 무시할 정도입니다. 브라우저마다 다를 수 있습니다. firstChild그래도 더 읽기 쉽다고 생각 합니다.
분쇄

17
while (oldParent.hasChildNodes()) newParent.appendChild(oldParent.firstChild);while (oldParent.firstChild) newParent.appendChild(oldParent.firstChild);작업 2 배 빠른 크롬 6 배에서 10 배 빠른 파이어 폭스한다. 수정 된 JSPerf
사용자

3
DocumentFragment developer.mozilla.org/en-US/docs/Web/API/DocumentFragment 를 사용 하고 성능 후에는 모든 요소를 ​​한 번에 이동 하는 것이 유용 할 수 있습니다 .
호르 나

10

현대적인 방법 :

newParent.append(...oldParent.childNodes);
  1. .append.appendChild. 가장 큰 차이점은 한 번에 여러 노드를 허용하고 심지어는 다음과 같은 일반 문자열을 허용한다는 것입니다..append('hello!')
  2. oldParent.childNodes이고 반복 가능한 가에 확산 될 수 있도록 ...여러 매개 변수가 될.append()

두 가지의 호환성 표 (요약 : Edge 17+, Safari 10+) :


매우 우아해 보입니다. 여기 다른 답변과 성능 차이가 있는지 궁금합니다.
Drew Noakes

있다면 최소한이어야합니다. append 여러 번 이 아닌 단일 호출 이기 때문에 더 빠릅니다 .
fregante 2019-08-08

경고 :하지 IE11 (결코, 아마도)에 대한
르네 반 Lende 데르

좋지만 몇 가지 간단한 테스트를 수행 while()했으며 Chrome에서는 여전히 약간 더 빠릅니다. 내 말을 받아들이지 말고 가능하면 자신의 테스트를 수행하십시오.
lepe

8

다음은 간단한 기능입니다.

function setParent(el, newParent)
{
    newParent.appendChild(el);
}

el의는 childNodes있습니다 이동하는 요소는, newParent 은 IS 요소 el로 이동합니다 당신이 좋아하는 기능을 수행 할 수 있도록 :

var l = document.getElementById('old-parent').childNodes.length;
var a = document.getElementById('old-parent');
var b = document.getElementById('new-parent');
for (var i = l; i >= 0; i--)
{
    setParent(a.childNodes[0], b);
}

다음은 데모입니다.


그의 코드와 함께 이것을 어떻게 사용 하시겠습니까? 이렇게 old-parent전달 하면 요소도 이동합니다 el.
분쇄

1
HTML을 렌더링합니다.<div id="new-parent"><div id="old-parent">...</div></div>
crush

1
아이를 움직일 때 길이가 변하기 때문에 그것은 작동하지 않습니다. 따라서 노드의 절반 만 이동하게됩니다. 거꾸로 반복하거나 내가 한 것처럼 while 루프를 사용해야합니다.
분쇄

여전히 작동하지 않습니다. 다음을 수행해야합니다. for (var i = l; i >= 0; i--)또는 while (document.getElementById('old-parent').length > 0). 또한 데모에 오류가 있습니다.
분쇄

편집에서 @crush 보면, SRY -while (document.getElementById('old-parent').length > 0) { setParent(document.getElementById('old-parent')[i], document.getElementById('new-parent')); }
Cilan

0

이 답변은 내부 코드 (innerHTML)를 하나에서 다른 코드로 전송하는 것 외에 다른 작업을 수행 할 필요가없는 경우에만 실제로 작동합니다.

// Define old parent
var oldParent = document.getElementById('old-parent');

// Define new parent
var newParent = document.getElementById('new-parent');

// Basically takes the inner code of the old, and places it into the new one
newParent.innerHTML = oldParent.innerHTML;

// Delete / Clear the innerHTML / code of the old Parent
oldParent.innerHTML = '';

도움이 되었기를 바랍니다!


1
이것은 실제로 HTML 문자열을 통해 직렬화 / 역 직렬화하고 싶지는 않지만 작동합니다. 그것은하지 작업 :하지만
드류 녹스

11
요소에 첨부 된 개체와 이벤트를 복사하지 않습니다.
Gregory Magarshak 2014

4
이것은 DOM을 재생성하며, 기존 노드 / 이벤트를 이동하지 않으며 모든 자식에 대한 루프보다 느릴 것입니다
Jordan

몇 가지 간단한 테스트를 실행했는데이 방법은 여전히 ​​허용되는 답변보다 느리고 이미 설명한대로 단점이 있습니다.
lepe

-1

-아이디 이름에 사용 하지 않으면 이렇게 할 수 있습니다.

oldParent.id='xxx';
newParent.id='oldParent';
xxx.id='newParent';
oldParent.parentNode.insertBefore(oldParent,newParent);
#newParent { color: red }
<div id="oldParent">
    <span>Foo</span>
    <b>Bar</b>
    Hello World
</div>
<div id="newParent"></div>

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.