문서 객체 모델 DOM (Document Object Model)
DOM 이란 Document Object Model의 약자입니다. 번역하자면 문서 객체 모델인데요.
여기서의 문서는 HTML 문서를 말한다.
브라우저는 웹 문서를 로드한 후, 파싱하여 DOM을 생성한다.
DOM은 모든 요소, 속성, 텍스트를 객체로 만들어 이 객체들을 부자 관계에 따라 트리 구조로 구성한 것을 의미한다.
정적인 웹페이지를 변경하는 유일한 방법은 DOM을 변경하는 것이며, 이 때 필요한 것이 DOM API이다.
DOM Tree 구성요소
- 문서 노드(Document Node) ➡️ 최상위 트리이자 접근의 시작점이다.
- 요소 노드(Element Node) ➡️ HTML 요소를 표현한다.
- 속성 노드(Attribute Node) ➡️ HTML 요소의 속성을 표현한다.
- 텍스트 노드(Text Node) ➡️ HTML 요소의 텍스트를 표현한다. 자식을 가질 수 없다.
✔️ <html> = document.documentElement
✔️ <body> = document.body
✔️ <head> = document.head
<html>
<head>
<title>DOM 공부하기</title>
</head>
<body>
<h1>DOM을 알아봅시다</h1>
<p>DOM 구조는 트리 모양입니다.</p>
</body>
</html>
DOM API
DOM을 통해 웹페이지를 조작하려면 다음에 맞게 API를 사용한다.
- 조작하고자하는 요소를 선택 또는 탐색한다.
- 선택된 요소의 콘텐츠 또는 어트리뷰트를 조작한다.
✍️ DOM 핵심 API
유형 | 메서드명 |
순회 | childNodes, firstChild, lastChild, nextSibling, previousSibling |
선택 | getElementById() , getElementsByTagName() getElementsByName(), getElementsByClassName() querySelector(), querySelectorAll() |
생성 / 추가 / 삭제 | createElement(), createTextNode(), appendChild(), removeChild() createAttribute() , setAttribute(), getAttribute() |
내용 저장 / 조회 | innerHTML, innerText, value |
DOM 노드 접근/선택
메서드명 | 설명 |
document.getElementById("id명") | * id 접근 / 하나의 요소 노드 선택 해당 아이디를 가진 요소를 선택해서 첫 번째 요소 하나를 객체 리턴 |
document.getElementsByClassName("class명") | * class 접근 / 여러 개의 요소 노드 선택 해당 클래스를 가진 요소들을 선택해서 요소들을 배열로 리턴 공백을 사용하면 여러 개의 class를 지정 HTMLCollection 형태로 반환 |
document.querySelector("cssSelector") | * css 선택자 접근 / 하나의 요소 노드 선택 CSS 선택자 문법으로 선택자에 해당하는 첫 번째 요소 하나를 객체 리턴 querySelector("선택자"); querySelector("#아이디명"); querySelector(".클래스명"); querySelector("태그명"); |
document.querySelectorAll("cssSelector") | * css 선택자 접근 / 여러 개의 요소 노드 선택 CSS 선택자 문법으로 선택자에 해당하는 요소들을 배열로 리턴 querySelectorAll("선택자"); querySelectorAll("#아이디명"); querySelectorAll(".클래스명"); querySelectorAll("태그명"); NodeList 형태로 반환 |
document.getElementsByTagName("tag명") | * 태그명 접근 해당 태그 요소들을 선택해서 요소들을 배열로 리턴 HTMLCollection 형태로 반환 |
DOM 노드(Node) / 엘리먼트(Element) 탐색
- Node : 태그(요소 노드), 속성, 주석, 내용(텍스트 노드)를 모두 표현
- Element : Node의 하위 개념으로 요소 노드만을 표현한다. 즉, 속성, 주석, 내용은 해당하지 않는다.
📝 노드(Node) 탐색
유형 | 종류 | 설명 |
부모 Node 탐색 | 요소.parentNode | 요소의 부모 노드를 탐색해서 반환 |
자식 Node 탐색 | 요소.childNodes | 요소의 자식 노드를 모두 반환 NodeList 형태 |
요소.firstChild | 첫 번째 자식 노드 탐색해서 반환 | |
요소.lastChide | 마지막 자식 노드를 탐색해서 반환 | |
요소.childNodes[인덱스] | 인덱스 n번째 자식 노드를 탐색해서 반환 | |
형제 Node 탐색 | 요소.previousSibling | 요소의 이전 형제 노드를 반환 |
요소.nextSibling | 요소의 다음 형제 노드를 반환 |
📝 엘리먼트(Element) 탐색
종류 | 설명 |
children | 자식 요소만 모두 선택 |
parentElement | 부모 요소 선택 |
firstElementChild | 첫 번째 자식 요소 선택 |
lastElementChild | 마지막 자식 요소 선택 |
previousSibling | 이전 형제 요소 선택 |
nextSibling | 다음 형제 요소 선택 |
DOM 노드 조작
📝 HTML 요소 생성/삽입/삭제
innerHTML을 사용하지 않고, 새로운 콘텐츠를 추가하는 방법
메서드명 | 설명 |
document.createElement("태그명") | html 요소 생성 태그이름을 인자로 전달하여 태그 요소를 생성 ex. let div = document.createElement('div'); |
document.createTextNode("텍스트") | 텍스트를 인자로 전달하여 텍스트 노드를 생성 ex. let text = document.createTextNode('안녕?'); |
추가할 노드의 부모노드.appendChild(추가할 노드) | html 요소 추가 해당 태그의 자식요소로 삽입하겠다. 추가할 노드의 부모 노드에 먼저 접근해야 한다. ex. // 텍스트 노드를 <div> 노드의 자식 노드로 추가 div.appendChild(text); // '<div>안녕?</div>' 노드를 문서의 body 파트에 붙여 넣는다. document.body.append(div); |
삭제할 노드의 부모노드.removeChild(삭제할 노드) | 인자로 전달한 노드를 DOM 트리에 제거 먼저 부모 노드에 접근해서 자식 노드를 삭제해야 한다. |
사용예시
const newBlock = document.createElement("div"); // html 요소 생성
newBlock.innerText = "shape"; // html 요소 내용 수정
newBlock.setAttribute("class","box1"); // html 요소에 attribute 설정하기
newBlcok.style.background = "#000"; // css style background 적용
document.body.appendChild(newBox1); // html 요소 추가 (body의 하부 요소로 추가)
📝 HTML 콘텐츠 조작
유형 | 메서드명 | 설명 |
내용 (Content) |
요소.innerText 요소.innerText = "값"; |
요소 안의 text 값 내용 조회/수정 (텍스트 내용) (내용을 덮어쓰는 방식) (부모요소를 잡으면 자식 것까지 다 가져온다) |
요소.innerHtml 요소.innerHtml = "<i>값</i>"; |
요소 내용 조회/수정 (텍스트 내용, HTML 태그 반영) (부모요소를 잡으면 자식 것까지 다 가져온다) |
|
요소의 속성 (Attribute) |
요소.getAttribute("속성명"); 요소.setAttribute("속성명", "값"); 요소.removeAttribute("속성명"); |
1. 요소의 특정 속성의 속성 값 반환 2. 요소에 속성/값 설정,수정 (기존 정의된 style 지우고, 새로운 속성으로 덮어쓴다.) 3. 요소의 특정 속성 삭제 |
CSS 스타일 (Style) |
요소.style 요소.style.스타일속성명 = "값"; |
1. inline으로 정의된 style 속성만 가져온다. 2. 기존 정의 된 style에서 새로운 속성 추가 * 카멜표기법 사용 background-color → backgroundColor list-style-type → listStyleType ex. <p>권소현</p> const text = document.querySelector("p"); text.style.color = "hotpink"; |
요소.style.cssText = "값"; | 기존 정의된 style 지우고, 새로운 속성으로 덮어쓴다. ex. const text = document.querySelector("p"); text.style.cssText = "padding: 20px 0; color: hotpink; background-color: beige"; |
|
getComputedStyle(요소); | inline으로 정의된 style 속성 뿐 아니라 CSS 파일 내 stlye 속성도 함께 가져온다. ex. <span style='padding: 20px; color: hotpink;'> 권소현 </span> const text = document.querySelector("span"); print.innerText += getComputedStyle(text).color; |
DOM 이벤트 처리
웹페이지에서 마우스 클릭, 키보드를 입력, 특정요소에 포커스가 이동될 때 어떤 사건을 발생
- DOM Level 0 ➡️ 인라인 이벤트 핸들러 : HTML 요소의 이벤트 처리기 속성에 설정
- DOM Level 0 ➡️ 이벤트 핸들러 프로퍼티 : DOM 요소 객체의 이벤트 처리기 프로퍼티에 설정
- DOM Level 2 ➡️ addEventListner() 메서드
this 키워드
이벤트 함수 내부에서 this 키워드를 사용하면 이벤트가 발생한 요소 노드를 바로 가리킬 수 있다.
단, 화살표 함수일 때는 이벤트 객체의 target 속성으로 참조해야 한다.
1. 인라인 이벤트 핸들러
HTML 태그의 속성(attribute)에 이벤트 속성을 추가하는 방법입니다.
이벤트명 앞에 on 접두사를 붙여 사용합니다. 자바스크립트 코드와 HTML이 혼합되기 때문에 비 권장되는 방법입니다.
* HTML 문서를 읽어들일 때 이벤트 처리기도 함께 설정하기 때문에 설정하기 쉬움
<!-- body 부분 -->
<button onclick="test()">버튼</button>
<!-- script 부분 -->
<script>
function test() { //click 이벤트 발생시 처리할 함수 등록
console.log("클릭!!");
}
</script>
2. 이벤트 핸들러 프로퍼티
HTML과 분리하여 스크립트 코드에서 DOM 객체의 프로퍼티(property)를 이용하는 방법입니다.
대상 DOM 요소에 on 접두사를 붙인 이벤트명으로 이벤트 핸들러 프로퍼티를 설정하고 이벤트 발생시 처리할 함수를 등록합니다.
* HTML과 자바스크립트를 분리해서 작성 가능
📝 이벤트 핸들러 형태
요소.on이벤트명 = 익명함수;
사용예시
var card = document.querySelector("#card");
card.onclick = function(event){
// 이벤트가 발생한 대상 객체에 접근하려면 이벤트 처리기에서 예약어 this를 사용
alert("클릭한 이미지 파일 : " + this.src);
}
3. addEventListner() 메서드
addEventListener() 메소드 방식 (표준 이벤트 모델)입니다.
addEventListener() 메소드를 이용하여 대상 DOM 요소에 이벤트를 설정하고
해당 이벤트가 발생했을 때 실행될 이벤트 핸들러를 등록합니다.
이는 더 현대적인 방식으로서, 앞선 두 가지 방식보다 이점을 가지고 있습니다.
인라인 이벤트 핸들러 방식, 이벤트 핸들러 프로퍼티 방식은 각 요소에 이벤트 타입별로 하나의 이벤트 핸들러만 연결할 수 있는 반면,
addEventListener() 메소드 방식은 여러 개의 이벤트 핸들러를 연결할 수 있습니다.
또한, 이전에 추가한 이벤트 핸들러를 제거하는 removeEventListener()라는 대응 관계에 있는 함수가 제공됩니다.
📝 addEventListner() 형태
요소.addEventListener('이벤트타입', 익명함수);
사용예시
document.querySelector("#out")("mouseover", function(){
// 이벤트를 발생시켰을 시 실행할 동작 (이것도 콜백함수)
this.style.backgroundColor = "red";
});
📝 이벤트 타입별 주요 이벤트 (리소스,마우스,키보드,폼,포커스,UI)
이벤트 취소
preventDefault() 메서드를 사용하면 태그에 기본으로 연결된 이벤트를 취소할 수 있다.
분류 | 이벤트명 | 발생 타이밍 | 주된 대상 요소 |
리소스 |
load |
DOMContentLoaded 이벤트가 발생한 이후, 모든 리소스(이미지, 폰트 등)의 로딩이 완료되었을 때 |
body, img |
unload | 다른 페이지로 이동할 때 리소스가 언로드 될 때 (주로 새로운 웹페이지를 요청한 경우) |
body | |
abort | 리소스 로딩이 중단되었을 때 | img | |
error |
리소스 로딩이 실패했을 때 | img | |
마우스 | click | 마우스 버튼을 클릭했을 때 | |
dblclick | 마우스 버튼을 더블 클릭했을 때 | ||
mousedown | 마우스 버튼을 누르고 있을 때 | ||
mouseup | 누르고 있던 마우스 버튼을 뗄 때 | ||
mousemove | 마우스를 움직일 때 (터치스크린에서 동작 x) |
||
mouseover | 마우스를 요소 위로 움직였을 때 (터치스크린에서 동작 x) |
||
mouseout | 마우스를 요소 밖으로 움직였을 때 (터치스크린에서 동작 x) |
||
contextmenu | context menu가 표시되기 전 | body | |
키보드 | keydown | 모든 키를 눌렀을 때 발생 | |
keyup | 누르고 있던 키를 놓았을 때 한번만 발생 | ||
keypress | 문자 키를 눌렀을 때 연속적으로 발생 | ||
폼 |
input |
input(text, checkbox, radio), select, textarea 요소의 값이 입력되었을 때 |
|
change | input(text, checkbox, radio), select, textarea 요소의 값이 변경되었을 때 |
input(text), select | |
submit | form 요소 내의 submit 버튼을 클릭했을 때 | form | |
reset | form 요소 내의 reset 버튼을 클릭했을 때 | form | |
포커스 |
focus | HTML 요소가 포커스를 받았을 때 (버블링 x) | |
blur | HTML 요소가 포커스를 잃었을 때 (버블링 x) | ||
focusin | HTML 요소가 포커스를 받았을 때 (버블링 o) | ||
focusout | HTML 요소가 포커스를 잃었을 때 (버블링 o) | ||
UI | resize | 브라우저 윈도우(window)의 크기를 리사이즈할 때 연속적으로 발생(window객체만) |
|
scroll | 웹페이지(document) 또는 HTML 요소를 스크롤할 때 연속적으로 발생 |
body |