DOM은 Document Object Model의 약자로, HTML 요소를 Object 처럼 조작할 수 있는 Model을 의미한다. 즉, JavaScript를 사용할 수 있으면, DOM으로 HTML을 조작이 가능하다.
HTML문서를 분석하여 HTML의 아주 작은 부분까지 접근할 수있는 구조를 만들었는데 이렇게 만들어진 구조를 DOM이라고 한다. DOM을 이용하면 HTML로 구성된 웹 페이지를 동적으로 움직이게 만들 수 있다.
HTML에서 javaScript를 적용하기 위해서 <script>
태그를 사용한다.
<script src="index.js"></script>
웹 브라우저가 작성된 코드를 해석하는 과정에서 <script>
요소를 만나면, 웹 브라우저는 HTML 해석을 잠시 멈춤, HTML 해석을 잠시 멈추고 <script>
요소를 먼저 실행한다.
HTML 문서를 파싱하는 중에 <script>
태그를 만나 js파일을 받아오고 실행한 뒤, 다시 HTML문서를 파싱하게 됨.. Js 파일 크기가 엄청나게 클 경우 렌더링이 너무 오래걸리게 되어 사용자가 페이지를 보기까지 너무 오래걸릴 수 있기 때문에 좋은 방법이라고 보기는 어려움
HTML 문서를 파싱을 먼저 하고 JS 파일을 받아오게 됨 body
에 삽입하게 될 경우 화면 렌더링에서는 좀 효과적일 수 있으나 HTML파일 크기가 큰 경우 JS가 포함된 컨텐츠를 보기 위해서는 너무 오래걸릴 수 있음
async
와defer
은 HTML5에 새로 추가된 스크립트 속성이다. 이 두가지 속성은 HTML파싱과 스크립트 다운로드를 병렬로 진행함
HTML 문서와 같이 병렬적으로 파싱을 진행하다 JS 실행 단계에서는 HTML문서 파싱을 잠시 중지하고 JS실행이 끝나면 다시 HTML 문서 파싱을 재시작하기 때문에 HTML이 모두 실행되기 전 JS 가 실행되게 된다.
단! 다수의 스크립트 파일을 다운받게 되면 다운로드가 완료되는 순으로 JS 파일을 실행하기 때문에 순서에 상관없이 실행된다.
<script async src="index.js"></script>
HTML 문서와 Js파일을 모두 다운로드 받아놓고 파싱이 끝난 순서대로 Js파일을 실행하기 때문에 원하는 방향으로 스크립트 실행 가능하다.
<script defer src="index.js"></script>
결론) 외부 스크립트를 불러올 때에는 defer 속성을 사용하는 것이 최선이고 순서 상관 없고 빨리 실행하는게 중요할 경우에는 async 속성 사용을 추천
document
객체에는 많은 속성과 메서드가 존재하지만, 지금 당장은 CRUD에 집중해야 한다.
querySelector는 셀렉터를 조회한다는 의미를 가지고 있으며 class_div라는 class값을 가진 div의 엘리먼트의 정보를 divEl에 담아둘 수 있음
const divEl = document.querySelector('.class_div');
HTML문서 안에 class_div라는 클래스명을 가진 요소가 여러 개 일 때는 querySelectorAll
을 사용함! 이렇게 조회한 HTML요소들은 배열처럼 for문을 사용할 수도 있음 하지만 진짜 배열은 아니 아닌 '유사 배열', '배열형 객체' 등 다양한 이름으로 부름
const divEl = document.querySelectorAll('.class_div');
document 객체 안에 있는 createElement는 지정한 태그의 HTML 요소를 만들어 반환함
const oneDiv = document.createElement('div');
원래 지정 요소의 class 명을 읽을 수 있는 읽기 전용 속성이지만 여러 메소드를 사용하여 연결된 속성을 사용할 수 있음
classList.add를 이용해 oneDiv에 클래스 추가
oneDiv.classList.add('class_div')
위에서 생성한 oneDiv에 textContent라는 메서드를 활용하여 텍스트 컨텐츠를 추가할 수 있음
const Div = document.querySelector('.class_div')
Div.textContent = 'div입니다'
위에서 텍스트 컨텐츠를 추가한 후 화면에 보이게 하려면 append를 사용하여 기존의 트리구조에 연결시켜줘야 함
document.body.append(oneDiv)
innerHTML을 이용하여 body안에 모든 자식 요소를 간편하게 지울 수 있지만, innerHTML은 보안에서 몇 가지 문제를 가지고 있어 사용을 지양한다.
document.body.innerHTML = '';
🚫 XSS (Cross-Site Scripting) 공격에 취약하다는 약점을 가지고있음
element 속성으로 해당 요소 내에서 사용자에게 보여지는 텍스트 값을 읽어온다. 연속되는 공백이 있을 시 하나의 공백으로 처리한다.
<div class="my_div">
안녕하세요 !
<span> 텍스트 <spna>
</div>
//innerHTML 출력 결과
안녕하세요! 텍스트
Node의 속성으로, innerText와 달리 <script>
나 <style>
요소를 포함한 모든 요소의 콘텐츠를 값을 가져온다. 반면 innerText는 "사람이 읽을 수 있는" 요소만 처리한다.
textContent는 노드의 모든 요소를 반환하지만, innerText는 스타일링을 고려하며, "숨겨진" 요소의 텍스트는 반환하지 않는다.
<div class="my_div">
안녕하세요 !
<span> 텍스트 <spna>
</div>
// TextContent 출력 결과
안녕하세요!
텍스트
innerHTML 대신할 메서드인 removeChild는 자식 요소를 지정해서 삭제할 수 있음
해당 코드는 container에 자식 요소가 남아있지 않을 때까지, 첫 번째 자식 요소를 삭제함
const container = document.querySelector('#container');
while (container.firstChild) {
container.removeChild(container.firstChild);
}
remove 메서드는 DOM에서 요소를 제거할 수 있음
해당 코드는 tweet라는 클래스를 가진 모든 요소를 삭제함
const tweets = document.querySelectorAll('.tweet')
tweets.forEach(function(tweet){
tweet.remove();
})
혹은 아래와 같이 for of 문도 가능 ⭕
해당 코드는 tweet라는 클래스를 가진 모든 요소를 삭제함
const tweets = document.querySelectorAll('.tweet')
for (let tweet of tweets){
tweet.remove()
}
태그, 텍스트, 주석 등을 모두 포함한 것
<!DOCTYPE html>
<html>
<head>
<title>My Page</title>
</head>
<body>
<!-- Page Body -->
<h2>My Page</h2>
<p id="content">Thank you for visiting my web page!</p>
</body>
</html>
위 문서는 다음과 같은 node 구조를 가지고 있음
DOCTYPE : html
HEML
ㄴHEAD
ㄴTITLE
ㄴ#text : My Page
ㄴBODY
ㄴ #comment : Page Body
ㄴ H2
ㄴ#text : My Page
ㄴ p id= "content"
ㄴ#text : Thank you for visiting my web page!
element는 node의 한 종류로 주로 <p>
<div>
같은 태그를 사용해서 작성된 노드를 말함 위 문서의 element는 <html>,<head>,<title>,<body>,<h2>,<p>
가 있음
주로 javaScript를 이용해서 DOM을 탐색하고 조작할 때는 이 element를 조작하는 경우가 많음
<body>
<!-- 안녕하세요 -->
<div>
<h2>JUNGHO BLOG</h2>
<p id="content">블로그에 방문해주셔서 감사합니다!</p>
<div>
<body>
현재 요소의 자식 노드가 포함된 노드의 리스트를 반환 이때 태그노드, 텍스트노드, 주석 노드 모두 포함
출력 결과
NodeList(6)0: text 1: h2 2: text 3: p#content 4: text 5: divlength: 6[[Prototype]]: NodeList
HTMLCollection(3) [h2, p#content, div, content: p#content]
let menus = document.querySelectorAll("button");
let btnAmericano = menus[0];
let btnCaffelatte = menus[1];
btnAmericano.onclick = handleClick;
btnCaffelatte.onclick = handleClick;
// for 문으로도 충분히 구현할 수 있는 내용입니다.
function handleClick(e) {
let currentMenu = e.target;
console.log(currentMenu + "를 클릭하셨습니다.");
}