본문 바로가기
JavaScript/JavaScript

Javascript) DOM 객체(Node 계열, Element 계열, 자식 요소-제거, 형제요소, 부모요소, 요소추가)

by 박채니 2022. 5. 29.

안녕하세요, 코린이의 코딩 학습기 채니 입니다.

 

개인 포스팅용으로 내용에 오류 및 잘못된 정보가 있을 수 있습니다.


DOM (Document Object Model)

- window.document

- 브라우저가 html 문서를 해석해서 document 객체 하위에 계층구조로써 html 태그 객체를 관리

- document.getElementByXXX, document.querySelectorXXX 메소드는 모두 DOM에서 검색하게 됨

- Node.prototype, Element.prototype 등을 상속하고 있음

 

HTML 코드

<div id="sample">
    <span>Hello</span>
    <!--Hello는 한국어로 안녕입니다.-->
</div>

<button onclick="test1();">#sample</button>

 

Javascript 코드

 

Node 계열

- TextNode

- CommentNode

- 모든 tag(Element)객체

 

Element 계열

- 모든 tag(Element)객체

const test1 = () => {
    console.dir(sample);
}

childNodes는 Node계열, children은 Element 계열을 보여줍니다.

따라서 children에는 tag객체인 [span] 이 포함되어있으며 childNodes에는 tag객체(span) 이 외 TextNode, CommentNode도 포함 되어 있는 것을 확인할 수 있습니다.

Text에는 tag와 tag 사이의 '\n', '\t'를 data로 갖고 있으며, Comment에는 주석 내용인 'Hello는 한국어로 안녕입니다.'를 data로 갖고 있는 것을 확인할 수 있습니다.

 

 

textNode를 가진 Element 생성하기 (이벤트 핸들러를 바로 등록하기에 유용)

- <h2>안녕하세요</h2>

 

HTML 코드

<button onclick="test2();">Element - textNode</button>

 

Javascript 코드

const test2 = () => {
    const h2 = document.createElement("h2"); // <h2></h2>
    const content = document.createTextNode("안녕하세요"); // 안녕하세요.
    h2.appendChild(content); // h2의 자식 요소로 추가 <h2>안녕하세요</h2>

    document.body.appendChild(h2); // body의 자식 요소로 맨 마지막에 추가(DOM에 추가)
};

h2태그를 createElement로 생성, textNode를 createTextNode로 생성한 후 생성한 Element h2의 자식 요소로 추가해주었습니다.

여기까진 메모리 상의 작업이며, 화면의 랜더하기 위하여 body의 자식 요소로 맨 마지막에 추가해주었습니다.

 

 

textNode가 없는 Element 생성하기

- img element 생성

 

HTML 코드

<button onclick="test3();">Element</button>

 

Javascript 코드

const test3 = () => {
    const img = document.createElement("img"); // <img>
    img.src = "../../sample/image/hyunta.jpg";
    img.style = "width:200px; margin: 10px; border-radius: 50%;";
    document.body.append(img);
};

 


자식요소

 

HTML 코드

<button onclick="test4();">자식요소</button>

<div id="foo">
    <p id="p1">안녕1</p>
    <p id="p2">안녕2</p>
    <p id="p3">안녕3</p>
    <p id="p4">안녕4</p>
    <p id="p5">안녕5</p>
</div>

 

Javascript 코드

const test4 = () => {
    console.dir(foo);
};

 

Node 속성

- firstChild

-  lastChild

- childNodes

console.log(foo.firstChild);
console.log(foo.lastChild);
console.log(foo.childNodes);

첫번째, 마지막 자식 요소(Node)를 가져왔기 때문에 tag와 tag사이의 '\n', '\t'를 data로 갖고 있는 것을 확인할 수 있습니다.

childNodes를 통해 모든 Node 계열 속성들을 가져왔습니다.

 

 

Element 속성

- firstElementChild

- lastElementChild

- children

console.log(foo.firstElementChild);
console.log(foo.lastElementChild);
console.log(foo.children);

마찬가지로 첫번째, 마지막 자식 요소(Element)를 가져왔기 때문에 p1, p5가 출력되었으며, children을 통해 모든 Element 계열 속성들을 가져왔습니다.

 


요소 및 태그 제거

 

모든 자식 요소 제거

while(foo.firstChild) 
    foo.removeChild(foo.firstChild);

자식 요소들만 제거하였기 때문에 <div> 태그 자체는 남아있는 것을 확인할 수 있습니다.

 

 

태그 자신을 직접 제거

HTML 코드

<button onclick="test5();">요소제거</button>

 

Javascript 코드

const test5 = () => foo.remove();

<div> 태그 자체가 제거된 것을 확인할 수 있습니다.

 


형제요소

 

HTML 코드

<button onclick="test6();">형제요소</button>

 

Javascript 코드


Node 속성

- nextSibling : 다음 Node 요소

const test6 = () => {
    console.log(foo.childNodes);

    const node = p3.nextSibling;
    console.log(node);
};

p3의 다음 Node 요소를 가져왔으므로 6번지의 text ('\n\t')를 가져온 것을 확인할 수 있습니다.

 

const node = p3.nextSibling.nextSibling;
console.log(node);

다음 다음 Node 요소를 가져왔기 때문에 7번지의 p4를 가져왔습니다.

 

- previousSibling : 이전 Node 요소

console.log(foo.childNodes);

const node = p3.previousSibling;
console.log(node);

p3의 이전 Node 요소를 가져왔으므로 4번지의 text('\n\t')를 가져왔습니다.

 

const node = p3.previousSibling.previousSibling;
console.log(node);

이전 이전 Node 요소를 가져왔으므로 3번지의 p2를 가져왔습니다.

 

 

Element 속성

- nextElementSibling : 다음 Element 요소

console.log(foo.childNodes);

const node = p3.nextElementSibling;
console.log(node);

p3 태그에서 다음 Element 요소인 7번지의 p4를 가져왔습니다.

 

const node = p3.nextElementSibling.nextElementSibling;
console.log(node);

다음 다음 Element 요소를 가져왔으므로 9번지의 p5가 출력되었습니다.

 

- previousSilbing : 이전 Element 요소

console.log(foo.childNodes);

const node = p3.previousElementSibling;
console.log(node);

p3의 이전 Element 요소를 가져왔으므로 3번지의 p2가 출력되었습니다.

 

const node = p3.previousElementSibling.previousElementSibling;
console.log(node);

이전 이전 Element 요소를 가져왔으므로 1번지의 p1가 출력되었습니다.

 

특정 Element 요소에 style 적용하기

- textNode에게는 style 속성이 없음!

const node = p3.previousElementSibling.previousElementSibling;
node.style.color = 'red';

 


부모 요소

- 자식을 가질 수 있는 것은 Element 뿐이기 때문에 결과는 동일

 

HTML 코드

<button onclick="test7();">부모요소</button>


Javascript 코드

 

Node 속성

- parentNode

const test7 = () => {
    const node = p3.parentNode;
    node.style.color = 'blue';
    console.log(node);
};

 

Element 속성

- parentElement

const node = p3.parentElement;
node.style.color = 'blue';
console.log(node);

자식을 가질 수 있는 것은 Element 요소이기 때문에 두 결과가 같은 것을 확인할 수 있습니다.

 

@실습 - textNode 변경하기 (p3에서 출발)

- #p2 컬러 pink

- #p5 컬러 tomato

- 부모 요소를 찾아 background-color 지정

- 자식 요소의 textNode를 Hello1, Hello2, Hello3, ... 로 변경

const test8 = () => {
    p3.previousElementSibling.style.color = 'pink';
    p3.nextElementSibling.nextElementSibling.style.color = 'tomato';
    p3.parentElement.style.backgroundColor = 'lightgray';

    [...p3.parentElement.children].forEach((child, index) => {
        child.replaceChild(document.createTextNode(`Hello${index+1}`), child.firstChild);
        // newNode, oldNode 순으로 전달하여 대체!
    });
};

 


요소 추가 - insertBefore

 

HTML 코드

<button onclick="test9();">요소 추가 - insertBefore</button>

 

Javascript 코드

 

parent.insertBefore(newNode, refNode)

- newNode를 refNode 앞에 추가

const test9 = () => {
    const mark = document.createElement("mark");
    mark.append(document.createTextNode('불금이다!')); // == mark.innerText = '불금이다!';

    foo.insertBefore(mark, p3);
};

p3 앞에 생성한 mark태그를 추가하였습니다.

 

 

요소 추가 - target.insertAdjacentHTML

 

HTML 코드

<button onclick="test10();">요소 추가 - insertAdjacentHTML</button>

 

Javascript 코드

 

target.insertAdjacentHTML(position, html)
- beforebegin : 시작 태그 전(형제요소)

const test10 = () => {
    const html = '<mark>HTML</mark>';

    p3.insertAdjacentHTML('beforebegin', html);
};

p3의 시작 태그 전에 html을 추가하였으므로 형제요소로 추가된 것을 확인할 수 있습니다.

 

- afterbegin : 시작 태그 직후(자식요소)

const html = '<mark>HTML</mark>';

p3.insertAdjacentHTML('afterbegin', html);

p3 태그의 시작 태그 직후에 html을 추가하였으므로 자식 요소로 추가된 것을 확인할 수 있습니다.

 

- beforeend : 종료 태그 직전(자식요소)

const html = '<mark>HTML</mark>';

p3.insertAdjacentHTML('beforeend', html);

p3 태그의 종료 태그 직전에 html을 추가하였으므로 자식 요소로 추가된 것을 확인할 수 있습니다.

 

- afterend : 종료 태그 후(형제요소)

const html = '<mark>HTML</mark>';

p3.insertAdjacentHTML('afterend', html);

p3 태그의 종료 태그 후에 html를 추가하였으므로 형제 요소로 추가된 것을 확인할 수 있습니다.