DOM은 HTML 문서의 계층적 구조와 정보를 표현하며 이를 제어할 수 있는 API
즉 프로퍼티와 메서드를 제공하는 틀 자료구조이다.
노드란 매듭, 절, 집합점, 중심점이라는 사전적 의미를 가지고 있으므로 여러 분야에서 넓게 이용되는 단어이다. 예를 들어 식물의 경우 줄기와 잎을 연결하는 곳을 노드라고 부르기도 한다.
HTML DOM은 노드(node)라고 불리는 계층적 단위에 정보를 저장하고 있다.
HTML DOM은 이러한 노드들을 정의하고, 그들 사이의 관계를 설명해 주는 역할을 함.
script
태그를 이용함.Q1). 그럼 script태그는 어디에 위치해야 하나요?
대표적으로 head
안쪽에 삽입하거나, body
태그가 끝나기 전에 삽입하거나 등이 있는데(2개 더있음)
body태그가 끝나기 전에 삽입
하자!
Example 1) HTML 예시
<html>
<body>
<div id="nav">
<div class="logo"></div>
<div class="menu-wrapper">
<div class="menu"></div>
<div class="menu"></div>
<div class="menu"></div>
<div class="profile-photo"></div>
</div>
</div>
<div id="news-contents">
<div class="news-content-wrapper">
<div class="news-picture"></div>
<div class="news-title"></div>
<div class="news-description"></div>
</div>
</div>
<div id="footer"></div>
</body>
</html>
자식 엘리먼트(element)
는 총 몇 개인가요? -> 3개 (id가 nav, news-contents, footer)console.dir(document.body);
console.dir
은 DOM을 객체의 모습으로 출력!
document.body
로 body의 속성 조회가능!
document.body.children
: 자식속성의 첫 번째 element 조회!Q. 아니 그럼 2번째는 ? 3번째는?? 변수로 저장하자!
let newsContents = document.body.children[1];
console.dir(newsContents) // div#news-contents
intro) document 객체에는 많은 속성과 메소드가 존재함. 모든 속성과 메소드를 외워야 할까? No.
지금 집중할 부분은 CRUD(Create, Read, Update and Delete)
createElement
: 새로운 엘리먼트를 만드는 도구const tweetDiv = document.createElement('div')
근데 이거 만으로는 안됨...
APPEND
(append, appendChild) document.body.append(tweetDiv) // body태그의 마지막으로 <div></div> 생성됨
이 메소드는 한 노드를 특정 부모 노드의 자식 노드 리스트 중 마지막 자식으로 붙인다.
-querySelector
, querySelectorAll - READ
querySelector 에 '.tweet' 을 첫 번째 인자로 넣으면, 클래스 이름이 tweet 인 HTML 엘리먼트 중 첫 번째 엘리먼트를 조회할 수 있습니다.
const oneTweet = document.querySelector('.tweet')
HTML 문서에는 클래스 이름이 tweet 인 엘리먼트가 여러 개 있는 데, 변수 oneTweet 에 할당된 엘리먼트는 단 하나!
여러 개의 엘리먼트를 한 번에 가져오기 위해서는, querySelectorAll 을 사용합니다.
이렇게 조회한 HTML 엘리먼트들은 배열처럼 for문을 사용하실 수 있다. 주의하세요! 앞서 조회한 HTML 엘리먼트들은 배열이 아닙니다! 이런 '배열 아닌 배열'을 유사 배열, 배열형 객체 등 다양한 이름으로 부릅니다. 정식 명칭은 Array-like Object 입니다.
const tweets = document.querySelectorAll('.tweet')
tweetDiv를 container의 마지막 자식 요소로 추가함.
const container = document.querySelector('#container')
const tweetDiv = document.createElement('div')
container.append(tweetDiv)
textContent
, classList.add - UPDATE textContent 를 사용해서, 비어있는 div 엘리먼트에 문자열을 입력합니다.
console.log(oneDiv) // <div></div> oneDiv.textContent = 'dev'; console.log(oneDiv) // <div>dev</div>
classList.add 를 이용해 div 엘리먼트에 class를 추가합니다.
oneDiv.classList.add('tweet')
console.log(oneDiv) // <div class="tweet">dev</div>
class 말고 다른 속성을 추가하려면
Element.setAttribute(name, value);
remove
, removeChild - DELETEremove 메소드를 사용해 삭제 가능
const container = document.querySelector('#container') const tweetDiv = document.createElement('div') container.append(tweetDiv) tweetDiv.remove() // 이렇게 append 했던 엘리먼트를 삭제할 수 있다.
removeChild 는 자식 엘리먼트를 지정해서 삭제하는 메소드
모든 자식 엘리먼트를 삭제하기 위해, 반복문(while, for, etc.)을 활용할 수 있음
다음의 코드는 자식 엘리먼트가 남아있지 않을 때까지, 첫 번째 자식 엘리먼트를 삭제하는 코드임
const container = document.querySelector('#container');
while (container.firstChild) {
container.removeChild(container.firstChild);
}
removeChild 와 while 을 이용해 자식 요소를 삭제하면, 제목에 해당하는 H2 "Tweet List"까지 삭제됨.
이를 방지하기 위한 방법은 여러 가지가 있습니다. 자식 요소가 담고 있는 문자열을 비교해 "Tweet List"만 남기거나, 새로운 변수를 생성하고 Tweet List를 할당해뒀다가 반복문이 끝난 뒤에 새롭게 추가할 수도 있습니다.
또는 자식 엘리먼트를 하나만 남기게 할 수도 있습니다.
const container = document.querySelector('#container');
while (container.children.length > 1) {
container.removeChild(container.lastChild);
}
container의 자식 엘리먼트가 1개만 남을 때까지, 마지막 자식 엘리먼트를 제거합니다.
또는 직접 클래스 이름이 tweet인 엘리먼트만 찾아서 지우는 방법도 있습니다.
const tweets = document.querySelectorAll('.tweet')
tweets.forEach(function(tweet){
tweet.remove();
})
// or
for (let tweet of tweets){
tweet.remove()
}
위는 클래스 이름이 tweet인 엘리먼트만 찾아서 제거합니다.
Further Study
아래 키워드에 대해서 직접 검색하여 학습하세요.