문서 객체 모델(Document Object Model, DOM)은 XML이나 HTML 문서에 접근하기 위한 일종의 인터페이스이다. 이 객체 모델은 문서 내의 모든 요소를 정의하고, 각각의 요소에 접근하는 방법을 제공한다.
자바스크립트는 DOM을 이용하여 속성, 스타일, 이벤트, 요소를 추가, 변경, 삭제할 수 있다.
Document 객체는 웹 페이지 그 자체를 의미한다.
웹 페이지에 존재하는 HTML 요소에 접근하고자 할 때는 반드시 Document 객체부터 시작해야한다.
Document 객체는 HTML 요소와 관련된 작업을 도와주는 다양한 메소드를 제공한다.
HTML 요소를 선택하기 위해 제공되는 메소드
1 ~ 4는 리스트로 해당 요소들을 전부 반환하지만 5번과 6번은 요소 한개만을 반환한다.
특히 5번의 선택자인 id는 HTML 파일내 존재하는 유일한값이여야한다.
새로운 HTML 요소를 생성하기 위한 메소드
HTML 요소에 이벤트 핸들러를 추가하기 위한 메소드
document.getElementById("b1").onclick = function(){
console.log('b1을 선택하셨습니다.');
}
document.querySelector("#b2").onclick = function(){
console.log('b2를 선택하셨습니다.');
}
HTML 요소를 다루기 위해서는 우선 해당 요소를 선택해야만 한다.
자바스크립트에서 특정 HTML 요소를 선택하는 방법은 다음과 같다.
<tag>
)getElementsByTagName() 메소드는 HTML 태그 이름을 이용하여 HTML 요소를 선택한다.
const buttons = document.getElementsByTagName("button");
console.log(buttons);
HTML 요소의 style 프로퍼티를 이용하면, 해당 요소의 CSS 스타일을 변경할 수 있다.
ex) buttons[0].style.color = 'red';
getElementById() 메소드는 아이디를 이용하여 HTML 요소를 선택한다.
const button1 = document.getElementById('b1');
button1.style.color = 'white';
console.log(button1);
자바스크립트에서 id를 이용한 선택은 해당 아이디를 가지고 있는 요소 단 하나만을 선택한다.
따라서 여러 요소를 선택하고 싶을 때는 태그 이름이나 클래스와 같은 다른 방법을 사용해야 한다.
getElementsByClassName() 메소드는 클래스 이름을 이용하여 HTMl 요소를 선택한다.
const btns = document.getElementsByClassName('btn');
console.log(btns);
getElementsByName() 메소드는 HTML 요소의 name 속성을 이용하여 HTML 요소를 선택한다.
const btns = document.getElementsByName('button');
querySelectorAll() 메소드는 CSS 선택자(아이디, 클래스, 속성, 속성값 등)를 이용하여 HTML 요소를 선택한다.
CSS선택자
HTML DOM을 이용하면 HTML 요소의 내용(content)이나 속성값 등을 변경할 수 있다.
<h1 id="title"></h1>
document.querySelector('#title').innerHTML = '자바스크립트를 이용한 요소의 내용 변경';
HTML 요소의 속성 이름을 이용하면 속성값도 변경할 수 있다.
HTML DOM을 이용하면 HTML 요소의 스타일(style)도 변경할 수 있다.
<h1 id="title"></h1>
const title = document.querySelector('#title');
title.innerHTML = '요소의 내용 변경 및 스타일 변경';
title.style.color = 'orangered';
HTML DOM은 노드(node)라고 불리는 계층적 단위에 정보를 저장하고 있다.
HTML DOM은 이러한 노드들을 정의하고, 그들 사이의 관계를 설명해 주는 역할을 한다.
W3C HTML DOM 표준에 따르면, HTML 문서의 모든 것은 노드이다.
문서 노드(document node) : HTML 문서 전체를 나타내는 노드
요소 노드(element node) : 모든 HTML 요소는 요소 노드이며, 속성 노드를 가질 수 있는 유일한 노드다.
속성 노드(attribute node) : 모든 HTML 요소의 속성은 속성 노드이며, 요소 노드에 관한 정보를 가지고 있다. 하지만, 속성 노드는 자식 노드(child node)에는 포함되지 않음
텍스트 노드(text node) : HTML 문서의 모든 텍스트는 텍스트 노드
주석 노드(comment node) : HTML 문서의 모든 주석은 주석 노드
HTML 문서에서 HTML DOM 노드에 접근하는 방법
getElementsByTagName() 메소드는 특정 태그 이름을 가지는 모든 요소를 노드 리스트의 형태로 반환한다. 따라서 이 메소드가 반환하는 노드 리스트를 이용하면 원하는 노드에 접근할 수 있다.
const divs = document.getElementsByTagName('div');
console.log(divs);
HTML DOM에서 노드 간의 관계는 6가지가 있다.
parentNode : 부모 노드
childNodes : 자식 노드 리스트
firstNode : 첫 번째 자식 노드
lastNode : 마지막 자식 노드
nextSibling : 다음 형제 노드
previousSibling : 이전 형제 노드
위와 같은 프로퍼티를 이용하여 원하는 노드에 손쉽게 접근할 수 있다.
<div id="parent">
parent Node
<div>
child Node1
</div>
<div id="child">
child Node2
</div>
<div>
child Node3
</div>
</div>
const parent = document.querySelector('#parent');
console.log(parent);
const parent = document.querySelector('#parent');
console.log(parent.firstChild);
console.log(parent.lastChild);
//firstNode, lastNode가 아니라 firstChild, lastChild이다.
const parent = document.querySelector('#parent');
console.log(parent.childNodes);
const child = document.querySelector('#child');
console.log(child.parentNode);
const child = document.querySelector('#child');
console.log(child.previousSibling); //text
console.log(child.nextSibling); //text
// 텍스트도 노드로 여겨진다.
노드 리스트는 getElementsByTagName() 메소드나 childNodes 프로퍼티의 값으로 반환되는 객체이다. 노드 리스트는 HTML 문서와 같은 순서로 문서 내의 모든 노드를 리스트 형태로 저장하고 있다. 리스트의 각 노드는 0부터 시작하는 인덱스를 이용하여 접근할 수 있다.
텍스트 노드도 노드이기 때문에 텍스트가 존재할 때 childNode를 사용할 경우 주의해야한다!
다음 메소드를 사용하면 특정 위치에 새로운 노드를 추가할 수 있다.
appendChild() 메소드는 새로운 노드를 해당 노드의 자식 노드 리스트의 맨 마지막에 추가한다.
<div id="parent">
parent Node
<div>
child Node1
</div>
<div >
child Node2
</div>
<div>
child Node3
</div>
</div>
<div id="child">
child Node4
</div>
const parent = document.querySelector('#parent');
console.log(parent);
const parent = document.querySelector('#parent');
const child = document.querySelector('#child');
parent.appendChild(child)
console.log(parent);
// 만약 이미 자식인 노드를 appendChild()의 파라미터로 넘길 경우
// 파라미터로 들어간 노드는 부모 노드의 가장 마지막 위치로 변경된다.
insertBefore() 메소드는 새로운 노드를 특정 자식 노드 바로 앞에 추가한다.
부모노드.insertBefore(새로운 자식 노드, 기준 자식 노드);
새로운 자식 노드 : 자식 노드 리스트(child node list)에 새롭게 추가할 자식 노드를 전달
기준 자식 노드 : 새로운 노드를 삽입할 때 기준이 되는 노드로, 이 노드 바로 앞에 새로운 노드 추가
<div id="parent">
parent Node
<div>
child Node1
</div>
<div id="child3">
child Node3
</div>
<div>
child Node4
</div>
</div>
<div id="child2">
child Node2
</div>
const parent = document.querySelector('#parent');
const child2 = document.querySelector('#child2');
const child3 = document.querySelector('#child3');
parent.insertBefore(child2,child3);
console.log(parent);
생성할 노드의 종류에 따라 다음과 같은 메소드를 사용할 수 있다.
createElement() 메소드를 사용하여 새로운 요소 노드를 만들 수 있다.
<div id="parent">
parent Node
<div>
child Node1
</div>
<div>
child Node2
</div>
<div>
child Node3
</div>
</div>
const parent = document.querySelector('#parent');
const btn = document.createElement('button');
btn.innerHTML = '새로생긴버튼입니다.';
parent.appendChild(btn);
createAttribute() 메소드를 사용하여 새로운 속성 노드를 만들 수 있다.
만약 같은 이름의 속성 노드가 이미 존재하면, 기존의 속성 노드는 새로운 속성 노드로 대체된다.
이미 존재하는 요소 노드에 속성 노드를 생성하고자 할 때에는 setAttribute() 메소드를 사용할 수 있다.
const parent = document.querySelector('#parent');
const btn = document.createElement('button');
let newAttribute = document.createAttribute('style');
newAttribute.value = "color:red";
btn.innerHTML = '새로생긴버튼입니다.';
btn.setAttributeNode(newAttribute);
parent.appendChild(btn);
createTextNode() 메소드를 사용하여 새로운 텍스트 노드를 만들 수 있다.
const parent = document.querySelector('#parent');
const text = document.createTextNode("새로운 텍스트 노드");
parent.appendChild(text);
다음 메소드를 사용하면 특정 노드를 제거할 수 있다.
removeChild() 메소드는 자식 노드 리스트에서 특정 자식 노드를 제거한다.
이 메소드는 성공적으로 노드가 제거되면 제거된 노드를 반환하며, 노드가 제거될 때에는 제거되는 노드의 모든 자식 노드들도 다 같이 제거된다.
<div id="parent">
parent Node
<div>
child Node1
</div>
<div id="child">
child Node2
</div>
<div>
child Node3
</div>
</div>
const parent = document.querySelector('#parent');
const child = document.querySelector('#child');
console.log(parent.removeChild(child));
// 자식 노드인 child는 제거되고, removeChild()메소드는 제거된 자식 노드를 반환한다.
removeAttribute() 메소드는 속성의 이름을 이용하여 특정 속성 노드를 제거한다.
<div id="parent">
parent Node
<div>
child Node1
</div>
<div id="child" style="color:red; font-size:24px;">
child Node2
</div>
<div>
child Node3
</div>
</div>
const parent = document.querySelector('#parent');
const child = document.querySelector('#child');
child.removeAttribute("style");
cloneNode() 메소드를 사용하면 특정 노드를 복제할 수 있다.
cloneNode() 메소드는 기존의 존재하는 노드와 똑같은 새로운 노드를 생성하여 반환한다.
복제할노드.cloneNode(자식노드복제여부);
자식 노드 복제 여부 : 전달된 값이 true이면 복제되는 노드의 모든 속성 노드와 자식 노드도 같이 복제하며, false이면 속성 노드만 복제하고 자식 노드는 복제하지 않는다.
child.cloneNode(true);
setAttribute() 메소드는 속성 노드의 속성값을 변경할 수 있다.
<div id="parent">
parent Node
<div>
child Node1
</div>
<div id="child" style="color:red; font-size:24px;">
child Node2
</div>
<div>
child Node3
</div>
</div>
const parent = document.querySelector('#parent');
const child = document.querySelector('#child');
child.setAttribute("style","color:blue; font-size: 32px; font-weight:bold;");