DOM이란
Document Object Model의 약자로, HTML 요소를 Object(JavaScript Object)처럼 조작(Manipulation)할 수 있는 Model
JavaScript를 사용할 수 있으면, DOM으로 HTML을 조작할 수 있습니다.
HTML을 조작할 수 있다는 게 무슨 뜻일까요? 여러 뛰어난 웹 개발자들이 모여 HTML을 분석하여 HTML의 아주 작은 부분까지 접근할 수 있는 구조를 만들었습니다. 이렇게 만들어진 구조를 DOM이라고 합니다. DOM을 이용하면 HTML로 구성된 웹 페이지를 동적으로 움직이게 만들 수 있습니다. 앞서 학습한 조건문과 반복문, 배열, 객체를 활용하면 소셜 미디어에서 새롭게 생성되는 게시물을 저장하고 분류하는 작업을 구현할 수 있습니다.
HTML에서 <script>의 위치
웹 브라우저가 작성된 코드를 해석하는 과정에서 <script> 요소를 만나면, 웹 브라우저는 HTML 해석을 잠시 멈춥니다. HTML 해석을 잠시 멈춘 웹 브라우저는 <script> 요소를 먼저 실행합니다.
1. <head> 안쪽
2. <body> 마지막
[HTML] script 태그는 어디에 위치 해야 할까?
처음 마크업을 배울 때, script 태그는 항상 head태그 내부에 위치하고 다음 body 태그에 ui요소를 넣었다. 하지만 어떤 영상을 보면 script 태그를 body 맨 하단에 위치하게 하는 경우를 볼 수 있다. 최
jae04099.tistory.com
요소 찾기
자바스크립트에서 DOM은 document 객체에 구현되어 있습니다. 브라우저에서 작동되는 자바스크립트 코드에서는, 어디에서나 document 객체를 조회할 수 있습니다.
구조를 조회할 때에는 console.dir 이 유용합니다. console.dir 은 console.log 와 달리 DOM을 객체의 모습으로 출력합니다. 앞으로 console.log 와 console.dir 의 차이를 구분해서 사용할 일이 계속 있습니다. 🙂
자식 요소 찾기
document.body 실행 시 body가 객체 형태로 보임.
body의 키 중 children에 body의 자식 요소들이 있음. document.body.children으로 바로 조회 가능
document.body.children //body의 children
document.body.children[2] // 2번 children
부모요소 찾기
자식요소.parentElement
DOM 구조도는 트리구조
body가 가장 상위에 있고, 아래에 여러 구성요소가 부모-자식 관계를 가지고 있습니다. 이 관계를 그려보면 아래와 비슷한 구조가 만들어집니다. 이런 자료 구조를 컴퓨터 공학에서는 트리 구조라고 합니다. 트리 구조의 가장 큰 특징은 부모가 자식을 여러 개 가지고, 부모가 하나인 구조가 반복되는 점입니다. 즉, 부모가 가진 하나 또는 여러 개의 자식 엘리먼트를 조회하는 코드를 작성한다면, 여러 번 반복해서 실행하는 코드가 필요합니다.
돔 다루기 (CRUD)
CREATE
요소 만들기
document.createElement('div')
const tweetDiv = document.createElement('div') //만드는 동시에 변수에 할당하기
요소를 만들어도 append가 되어있지 않기 때문에 웹페이지에서 보이지 않는다.
append
생성한 요소를 돔의 트리 구조와 연결
연결시킬 곳.append(연결할것)
document.body.append(tweetDiv)
textContent
요소에 글자 넣기
글자넣을곳.textContent = "글자"
tweetDiv.textContent = 'sherlock';
READ
DOM으로 HTML 엘리먼트의 정보를 조회하기 위해서는 querySelector의 첫 번째 인자로 셀렉터(selector)를 전달하여 확인할 수 있습니다. 셀렉터로는 HTML 요소("div"), id("#tweetList"), class(.tweet) 세 가지가 가장 많이 사용됩니다.
querySelector
const oneTweet = document.querySelector('.tweet')
HTML 문서에는 클래스 이름이 tweet 인 요소가 여러 개 있는 데, 변수 oneTweet 에 할당된 요소는 단 하나입니다. 여러 개의 요소를 한 번에 가져오기 위해서는, querySelectorAll 을 사용합니다. 이렇게 조회한 HTML 요소들은 배열처럼 for문을 사용하실 수 있습니다. 주의하세요! 앞서 조회한 HTML 요소들은 배열이 아닙니다! 이런 '배열 아닌 배열'을 유사 배열, 배열형 객체 등 다양한 이름으로 부릅니다. 정식 명칭은 Array-like Object 입니다. Array-like Object 같이 개념을 설명하는 용어는 영어로도 명확하게 기억해두는 게 좋습니다.
const getOneTweet = document.getElementById('container')
const queryOneTweet = document.querySelector('#container')
console.log(getOneTweet === queryOneTweet) // true
append
const container = document.querySelector('#container')
const tweetDiv = document.createElement('div')
container.append(tweetDiv) //tweenDiv가 container의 마지막 자식 요소로 추가됨
UPDATE
classList
부모 요소에 uppend해도 부모 요소의 자식들이 클래스로 묶여, 클래스 이름으로 css 스타일이 적용되어 있어 새로운 요소는 스타일 적용이 안된다. 새로운 요소에도 class를 추가하자.
요소.classList.add('클래스명')
oneDiv.classList.add('tweet')
console.log(oneDiv) // <div class="tweet">dev</div>
다른 attribute 추가 -> https://developer.mozilla.org/en-US/docs/Web/API/Element/setAttribute
Element.setAttribute() - Web APIs | MDN
Sets the value of an attribute on the specified element. If the attribute already exists, the value is updated; otherwise a new attribute is added with the specified name and value.
developer.mozilla.org
DELETE
1. 삭제하려는 요소의 위치를 알고 있을 때: remove
삭제할요소.remove()
tweetDiv.remove()
2. 전체 삭제: innerHTML = ''
document.querySelector('#container').innerHTML = '';
이 메서드는 보안 문제가 있음(https://developer.mozilla.org/en-US/docs/Web/API/Element/innerHTML#security_considerations)
2. 자식 요소를 지정해서 삭제: removeChild
모든 자식 요소를 삭제하기 위해, 반복문(while, for, etc.)을 활용할 수 있습니다.
//자식 요소가 남아있지 않을 때까지, 첫 번째 자식 요소를 삭제
const container = document.querySelector('#container');
while (container.firstChild) {
container.removeChild(container.firstChild);
}
//container의 자식 요소가 1개만 남을 때까지, 마지막 자식 요소를 제거
const container = document.querySelector('#container');
while (container.children.length > 1) {
container.removeChild(container.lastChild);
}
//직접 클래스 이름이 tweet인 요소만 찾아서 지우는 방법
const tweets = document.querySelectorAll('.tweet')
tweets.forEach(function(tweet){
tweet.remove();
})
// or
for (let tweet of tweets){
tweet.remove()
}