[240507] 39장 DOM (1)
DOM 은 HTML 문서의 계층적 구조와 정보를 표현하며 이를 제어할 수 있는 API, 즉 프로퍼티와 메서드를 제공하는 트리 자료 구조다.
노드
1. HTML 요소와 노드 객체
- HTML 요소는 렌더링 엔진에 의해 파싱되어 DOM을 구성하는 요소 노드 객체로 변환됨
- HTML 요소 간 중첩 관계에 의해 계층적인 부자 관계가 형성
- HTML 요서를 객체화한 모든 노드 객체들을 트리 자료 구조로 구성
- 노드 객체들로 구성된 트리 자료구조를 DOM (Document Object Model) 이라 함
2. 노드 객체의 타입
노드 객체는 총 12개의 종류가 있음
- 문서 노드 (document node)
- DOM 트리의 최사우이에 존재하는 루트 노드
- DOM 트리의 노드들에 접근하기 위한 진입점 역할
- 요소 노드 (element node)
- HTML 요소를 가리키는 객체
- 어트리뷰트 노드 (attribute node)
- 어트리뷰트가 지정된 HTML 요소의 요소 노드와 연결되어 있음
- 부모 노드가 없어서 형제 노드는 아님
- 텍스트 노드 (text node)
- 텍스트를 가리키는 객체
- 자식을 가질 수 없는 리프노드이다.
노드 객체의 상속 구조
- DOM 을 구성하는 노드객체는 ECMAScript 사양에 정의된 표준 빌트인 객체가 아니라, 브라우저 환경에서 추가적으로 제공하는 호스트 객체이다.
-
하지만 노드 객체도 자바스크립트 객체이므로 프로토 타입에 의한 상속 구조를 가짐
-
모든 노드 객체는 Object, EventTarget, Node 인터페이스를 상속 받음
-
프로토타입 체인에 있는 모든 프로토타입의 프로퍼티나 메서드를 상속받아 사용할 수 있음
- 노드 객체의 상속 구조는 개발자 도구의 Elements > Properties 패널에서 확인 가능
- DOM 은 HTML 문서의 계층적 구조와 정보를 표현하는 것은 물론 노드 객체의 종류, 타입에 따라 필요한 기능을 프로퍼티와 메서드의 집합인 DOM API 로 제공한다. DOM API 를 통해 HTML 구조나 내용, 스타일 등을 동적으로 조작 가능
요소 노드 취득
1. id 를 이용한 요소 노드 취득
Document.prototype.getElementById
- id 는 html 문서 내에서 유일해야함
- 요소에 어트리뷰트를 부여하면 id 값과 동일한 이름의 전역 변수가 암묵적으로 선언되고 해당 노드 객체가 할당되는 부수효과가 있음
- 단, 이미 전역 변수가 선언되어 있으면 노드 객체가 재할당 되지 않음
2. 태그 이름을 이용한 요소 노드 취득
Document.prototype/Element.prototype.getElementsByTagName
- 인수로 전달한 태그 이름을 갖는 모든 요소 노드 탐색해서 반환
- DOM 컬렉션 객체인 HTMLCollection 객체 반환함
- 유사 배열 객체, 이터러블임
const $elems = document.getElementsByTagName('li');
[...$elems].forEach(elem => { elem.style.color = 'red'; });
// 문서의 모든 요소를 취득하고 싶을때
const $all = document.getElementsByTagName('*');
3. class 를 이용한 요소 노드 취득
Document.prototype/Element.prototype.getElementsByClassName
- 공백으로 구분하여 여러 개의 class 지정 가능
- DOM 컬렉션 객체인 HTMLCollection 객체 반환함
4. css 선택자를 이용한 요소 노드 취득
* { ... } // 전체 선택자 : 모든 요소를 선택
p { ... } // 태그 선택자 : 모든 p 태그 요소를 모두 선택
#foo { ... } // id 선택자 : id 값이 'foo'인 요소를 모두 선택
.foo { ... } // 클래스 선택자
input[type=text] { ... } // 어트리뷰트 선택자 : input 요소 중에 type 어트리뷰트 값이 'text' 인 요소
div p { ... } // 후손 선택자 : div 요소의 후손 요소 중 p 요소 모두 선택
div > p { ... } // 자식 선택자
p + ul { ... } // 인접 형제 선택자, p 요소의 형제중에 p 요소 바로 뒤에 위치하는 ul 요소 선택
p ~ ul { ... } // 일반 형제 선택자, p 요소의 형제중에 p 요소 뒤에 위치하는 ul 요소 모두 선택
a:hover {...} // 가상 클래스 선택자 : hover 상태인 a 요소를 모두 선택
p::before {...} // 가상 요소 선택자 : p 요소의 콘텐츠 앞에 위치하는 공간을 선택 일반적으로 content 프로퍼티와 함께 사용
Document.prototype/Element.prototype.querySelector
메서드는 인수로 전달한 CSS 선택자를 만족시키는 하나의 요소 노드를 탐색하여 반환한다.- 여러 개인 경우 첫 번째 요소 노드만 반환
- 존재하지 않으면 null
- 문법이 맞지 않으면 DOMException 에러 발생
Document.prototype/Element.prototype.querySelector
메서드는 인수로 전달한 CSS 선택자를 만족시키는 모든 요소 노드를 탐색하여 반환한다.- 존재하지 않는 경우 빈 NodeList 객체 반환
- 문법이 맞지 않으면 DOMException 에러 발생
querySelector
querySelectorAll
메서드는getElementBy**
메서드보다 느린 것으로 알려져있지만, 더 구체적인 조건으로 요소를 취득할 수 있다는 장점이 있음- id 어트리뷰트가 있는 요소를 제외하고는
querySelector
querySelectorAll
메서드 권장
5. 특정 요소 노드를 취득할 수 있는지 확인
Element.prototype.matches
메서드는 인수로 전달한 CSS 선택자를 통해 특정 요소 노드를 취득할 수 있는지 확인함- 이벤트 위임을 사용할때 유용
6. HTMLCollection 과 NodeList
- DOM API 가 여러 개의 결과 값을 반환하기 위한 DOM 컬렉션 객체
- 둘 다 유사 배열 객체이면서 이터러블이다.
- for …of 문으로 순회 , 스프레드 문법으로 배열로 변환 가능
- 노드 객체의 상태 변화를 실시간으로 반영하는 살아 있는 객체이다.
- HTMLCollcetion 은 live 객체로 동작
- NodeList는 노드 객체의 상태 변화를 실시간으로 반영하지 않고 과거의 정적 상태를 유지하는 non-live 객체로 동작하지만 경우에 따라 live 객체로 동작할 때가 있음
HTMLCollection
- 실시간으로 반영하는 살아있는 DOM 컬렉션 객체
- 실시간으로 객체의 상태 변경을 반영하여 요소를 제거할 수 있어서 for 문 순회하면서 노드 객체의 상태를 변경해야할 때 주의해야함
- 역방향으로 순회하는 방법으로 회피 가능
- while 문으로 HTMLCollection 객체에 노드 객체가 남아 있지 않을때까지 무한 반복하는 방법으로 회피 가능
- HTMLCollection 객체를 사용하지 않는 것 ( […$elems] )
NodeList
- querySelectorAll 은 DOM 컬렉션 객체인 NodeList 객체 반환
- 실시간으로 노드 상태를 반영하지 않는다.
- NodeList.prototype은 forEach, item, entries, kets, values 메서드를 제공
- childNodes 프로퍼티가 반환하는 NodeList 객체는 실시간으로 live 객체로 동작하므로 주의
const $fruits = document.getElementById('fruits');
const { childNodes } = $fruits;
console.log(childNodes instanceof NodeList); // true
- 노드 객체의 상태 변경과 상관없이 안전하게 DOM 컬렉션을 사용하려면 HTMLCollection 이나 NodeList 객체를 배열로 변환하여 사용하는 것을 권장
Leave a comment