DOM은
HTML
문서의 계층적 구조와 정보를 표현하며 이를 제어할 수 있는 API
트리 자료구조
다.노드 객체로 변환
트리 자료 구조
로 구성다음 HTML
문서를 렌더링 엔진인 파싱한다고 생각해보자
렌더링 엔진은 위 HTML
문서를 파싱하여 다음과 같이 DOM
을 생성한다.
노드 객체는 상속 구조를 가지고 총 12개의 종류가 있다.
중요한 타입은 다음과 같이 4
가지다.
1.문서 노드(document node
)
2.요소 노드(element node
)
3.어트리뷰트 노드(attribute node
)
4.텍스트 노드(text node
)
Object
, EventTarget
, Node
인터페이스를 상속한다.DOM
은 HTML
문서의 계층적 구조와 정보를 표현하는 것은 물론 노드 객체의 종류이다.→ 노드 타입에 따라 필요한 기능을 프로퍼티와 메서드의 집합인 **DOM API
로 제공한다.**
→ 이 DOM API
를 통해 HTML
의 구조나 내용 또는 스타일 등을 동적으로 조작 가능하다.
Document.prototype.getElementById
메서드 사용한다.첫 번째 요소 노드
만 반환한다.Document.prototype
/Element.prototype.getElementByTagName
메서드는 인수로 전달한 태그 이름을 갖는 모든 요소 노드들을 탐색하여 반환한다.배열
이나 객체
와 같은 자료구조에 담아 반환해야 한다.Document.prototype
/Element.prototype.getElementByClassName
메서드는 인수로 전달한 class 어트리뷰트 값이 갖는 모든 요소 노드들을 탐색하여 반환한다.CSS
선택자는 스타일을 적용하고자 하는 HTML
요소를 특정할 때 사용하는 문법이다.Document.prototype
/Element.prototype.querySelecter
메서드는 인수로 전달한 CSS선택자를 만족시키기는 하나의 요소 노드를 탐색하여 반환한다.CSS
선택자를 만족시키는 요소 노드가 여러 개인 경우 첫 번째 요소 노드
만 반환한다.CSS
선택자를 만족시키는 요소 노드가 존재하지 않는 경우 null
을 반환한다CSS
선택자가 문법에 맞지 않는 경우 DOMException
에러가 발생한다.Element.prototype.matches
메서드는 인수로 전달한 CSS
선택자를 통해 특정 요소 노드를 취득할 수 있는지 확인한다.Element.prototype.matches
메서드는 이벤트 위임을 사용할 때 유용하다.HTMLCollection
은 객체의 상태 변화를 실시간으로 반영한다.// class 값이 'red'인 요소 객체를 모두 HTMLCollection 으로 반환
const $elems = document.getElementsByClassName('red');// 객체 상태가 실시간으로 반영되면서 for문 으로 사용할 경우 원하는 대로 조작하기 어려움
// 배열로 변환해서 사용
[...$elems].forEach(ele => ele.className = 'blue');
NodeList.prototype.forEach
메서드를 상속 받아 사용할 수 있다.childNodes
프로퍼티가 반환하는 NodeList
객체는 HTMLCollection
과 같이 상태가 실시간으로 반영한다노드 객체의 상태 변경과 상관없이 사용하려면 HTMLColleciton
이나 NodeList
객체를 배열로 변환해서 사용을 권장한다.
두 객체는 모두 유사 배열
이면서 이터러블
이다.
→ 스프레드 문법으로 배열로 변환 가능하다.
DOM
트리 상의 노드를 탐색할 수 있도록 Node
,Element
인터페이스는 트리 탐색 프로퍼티를 제공한다.Node.prototype.hasChildNodes
메서드를 사용한다.true
, 존재하지않으면 false
를 반환한다.firstChild
프로퍼티로 접근할 수 있다.Node.prototype.parentNode
프로퍼티를 사용한다.nodeValue
참조하면 null
반환한다.<!DOCTYPE html>
<html>
<body>
<div id="foo">Hello</div>
</body>
<script>
<-- 1. #foo 요소 노드의 자식 노드인 텍스트 노드를 취득한다. -->
const $textNode = document.getElementById('foo').firstChild;
<-- 2. nodeValue 프로퍼티를 사용하여 텍스트 노드의 값을 변경한다. -->
$textNode.nodeValue = 'World';
</script>
</html>
textContent
는 요소노드의 콘텐츠 영역(시작 태그와 종료태그 사이)의 모든 텍스트를 모두 반환한다.<!DOCTYPE html>
<html>
<body>
<div id="foo">Hello <span>world!</span></div>
</body>
<script>
// #foo 요소 노드의 텍스트를 모두 취득한다. 이때 HTML 마크업은 무시된다.
console.log(document.getElementById('foo').textContent); // Hello world!
</script>
</html>
HTML
마크업을 문자열
로 반환innerHTM
L 프로퍼티에 문자열을 할당하면 요소노드의 모든 자식노드가 제거되고 할당한 문자열의 파싱되어 DOM에 반영<!DOCTYPE html>
<html>
<body>
<ul id="fruits">
<li class="apple">Apple</li>
</ul>
</body>
<script>
const $fruits = document.getElementById('fruits');
<-- 노드 추가 -->
$fruits.innerHTML += '<li class="banana">Banana</li>';
<-- 노드 교체 -->
$fruits.innerHTML = '<li class="orange">Orange</li>';
<-- 노드 삭제 -->
$fruits.innerHTML = '';
</script>
</html>
innerHTML
단점beforebegin
, afterbegin
, beforend
, afterend
)<!DOCTYPE html>
<html>
<body>
<!-- beforebegin -->
<div id="foo">
<!-- afterbegin -->
text
<!-- beforeend -->
</div>
<!-- afterend -->
</body>
</html>
Document.prototype.createElement(tagName)
메서드는 요소 노드를 생성하여 반환한다.tagName
인수에는 태그 이름을 나타내는 문자열을 전달한다.createElement
메서드로 생성한 요소 노드는 기존 DOM
에 추가되지 않고 홀로 존재하는 상태로, 이후에 DOM
에 추가하는 처리가 필요하다.createElement
메서드로 생성한 요소 노드는 아무런 자식 노드가 없는 상태이다.Document.prototype.createTextNode(text)
메서드는 텍스트 노드를 생성하여 반환한다.createTextNode
메서드로 생성한 텍스트 노드는 요소 노드의 자식 노드에 추가되지 않고 홀로 존재하는 상태로, 이후에 요소 노드에 추가하는 처리가 필요하다.Node.prototype.appendChild(childNode)
메서드는 인수로 전달한 노드를 메서드를 호출한 노드의 마지막 자식 노드로 추가한다.childNode
인수에는 추가할 자식 노드를 전달한다.textContent
프로퍼티를 사용하여 텍스트 노드를 추가하는 것이 더욱 간편하다.textContent
프로퍼티에 문자열을 할당하면 요소 노드의 모든 자식 노드가 제거되고 할당한 문자열이 텍스트로 추가되므로 주의!HTML
문서가 파싱 될 때 어티리뷰트는 어티리뷰트 노드로 변환 되어 요소 노드와 연결 된다.NamedNodeMap
객체에 담겨서 요소 노드의 attributes
프로퍼티에 저장한다.Element.prototype.getAttirbute(attributeName)
: 어트리뷰트 값을 참조Element.prototype.setAttirbute(attributeName, attributeValue)
: 어트리뷰트 값을 변경Element.prototype.hasAttirbute(attributeName)
: 어트리뷰트 존재하는지 확인Element.prototype.removeAttirbute(attributeName)
: 특정 어트리뷰트 삭제HTML
어트리 뷰트는 중복 관리 되는 것처럼 보인다.attributes
프로퍼티에서 관리하는 어트리뷰트 노드DOM
프로퍼티HTMLElement.prototype.style
프로퍼티getter
/ setter
가 모두 존재하는 접근자 프로퍼티로 요소 노드의 인라인 스타일을 취득하거나 추가 또는 변경한다.<!DOCTYPE html>
<html>
<body>
<div style="color: red">Hello World</div>
<script>
const $div = document.querySelector('div');
<-- 인라인 스타일 취득 -->
console.log($div.style); // CSSStyleDeclaration { 0: "color", ... }
<-- 인라인 스타일 변경 -->
$div.style.color = 'blue';
<-- 인라인 스타일 추가 -->
$div.style.width = '100px';
$div.style.height = '100px';
$div.style.backgroundColor = 'yellow';
</script>
</body>
</html>
DOM
프로퍼티는 class
가 아니라 className
과 classList
Element.prototype.className
class
어트리뷰트의 값을 문자열로 반환한다.Element.prototype.classList
class
어트리뷰트의 정보를 담은 DOMTokenList
객체를 반환한다.DOMTokenList
객체는 class 어트리뷰트의 정보를나타내는 컬렉션 객체로 유사 배열이면서 이터러블DOMTokenList
주요 메서드add(... className)
: 인수로 전달된 1개의 이상의 문자열을 class 어트리뷰트 값으로 추가remove(... className)
: 인수로 전달한 1개 이상의 문자열과 일치하는 class 어트리뷰트에서 삭제한다.(일치 하는 클래스가 없으면 무시됨)item(index)
: 인수로 전달한 index에 해당하는 클래스를 class 어트리뷰트에서 반환한다.contains(className)
: 인수로 전달한 문자열과 일치하는 클래스가 class 어트리뷰트에 포함되어 있는지 확인한다.replace(oldClassName, newClassName)
: 첫 번째 인수 클래스를 두번째 클래스로 변경한다.toggle(className[, force])
: 인수로 전달한 문자열과 일치하는 클래스가 존재하면 제거하고 존재하지 않으면 추가한다.