DOM은 Document Object Model의 약자로, HTML 요소를 Object(JavaScript Object)처럼 조작(Manipulation)할 수 있는 Model
자바스크립트를 사용할 수 있으면, DOM으로 HTML을 조작할 수 있다.
자바스크립트에서 DOM은 document
객체에 구현
브라우저에서 작동되는 자바스크립트 코드에서는, 어디에서나 document 객체를 조회할 수 있다.
HTML에 JavaScript를 적용하기 위해서는 <script>
태그를 이용, <script>
요소는 등장과 함께 JavaScript가 실행된다
<script>
요소를 <head>
에 넣을 경우
body에 들어가는 script는 진행되지 않는다. script요소가 이미 head에서 실행됐기 때문이다.
<body>
태그가 끝나기 전에 삽입하는 경우
html의 body가 모두 진행되고 script요소가 실행되기 때문에 모든 script가 진행된다.
그러므로 <body>
태그 마지막에 script 요소를 집어넣어줘야 올바르게 진행된다.
HTML이 JavaScript에서는 어떻게 표현될까?
<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>
위의 예시에서 body element의 자식 element의 개수는 총 3개다.
<div id="nav">
, <div id="news-contents">
, <div id="footer">
(닫는 태그 생략)
<div class="logo">
같은 경우는 body element의 자식 element가 아닌 <div id="nav">
의 자식 element 이다.
console.dir(document.body); // document.body를 조회하는 명령어
//console.dir 은 console.log 와 달리 DOM을 객체의 모습으로 출력
자식 엘리먼트 찾기
console.dir(document.body.children)
body 안의 엘리먼트를 작성하면 바로 찾을 수 있다.
<div id="news-contents">
의 부모 엘리먼트 찾기
body 엘리먼트는 id가 news-contents div 엘리먼트의 부모 엘리먼트
console.dir(document.body.children[1])
이렇게 하면 <div id="news-contents">
를 조회할 수 있다.
Node.parentElement 는 부모 엘리먼트를 가리키는 속성이다.
<div id="news-contents">
의 부모를 찾기 위해서는 여러가지를 이용할 수 있는데 그중 ID를 가지고 있을 때 사용하는 요소 getElementById를 이용해보자
let newsC = document.getElementById('news-contents') //newsC라는 변수에 자식요소를 담아주고
let parent = newsC.parantNode; // newsC의 부모 엘리먼트를 찾는다. 이렇게 되면 부모엘리먼트를 가르킬 수 있다.
document.createElement('div') // 임의의 <div></div> 만든다. (소속된 곳 없음)
const menu = document.createElement('div') //새롭게 생성한 div element를 변수에 할당
createElement를 이용하면 HTML에 element를 추가하지 않고 js로도 추가할 수 있다.
document.body.append(menu) // 변수 menu를 body 엘리먼트에 append(추가)해줌
//임의의 엘리먼트를 다른 엘리먼트에 연결해주는 것
append 와 appendChild는 모두 부모노드에 자식노드를 연결해주는 메서드이다.
둘의 차이점을 간단하게 나타낸 블로그이다.
https://webruden.tistory.com/634
참고) 같은 엘리먼트를 appendChild 하면 복사되지 않는다. a, b로 변수가 지정되어있는 두개의 엘리먼트 중 a 안에 span 태그가 있고 이 span 태그를 b.appendChild('span') 한다면 a의 태그는 사라지고 b로 옮겨져 있다.
DOM으로 HTML 엘리먼트의 정보를 조회하기 위해서는 querySelector의 첫 번째 인자로 셀렉터(Selector)를 전달하여 확인
셀렉터로는 HTML 태그("div"), id("#nav"), class(".menu") 세 가지가 가장 많이 사용
querySelector 에 '.menu' 을 첫 번째 인자로 넣으면, 클래스 이름이 menu 인 HTML 엘리먼트 중 첫 번째 엘리먼트를 조회할 수 있다.
const oneTweet = document.querySelector('.menu')
여러 개의 엘리먼트를 한 번에 가져오기 위해서는, querySelectorAll 을 사용
이렇게 조회한 HTML 엘리먼트들은 배열처럼 for문을 사용할 수 있다. 배열처럼이지만 배열은 아니다.
const menus = document.querySelectorAll('.menu')
const menuWrapper = document.querySelector('.menu-wrapper')
const menuDiv = document.createElement('div')
menuWrapper.append(menuDiv)
//menuDiv를 menuWrapper의 마지막 자식 요소로 추가
let test = document.createElement('div')
console.log(test) // <div></div>
test.textContent = 'test check';
console.log(test) // <div>test check</div>
test.classList.add('profile-photo')
console.log(test) // <div class="profile-photo">test check</div>
const menuWrapper = document.querySelector('.menu-wrapper')
menuWrapper.append(test)
자식요소를 추가한 결과
<div class="menu-wrapper">
<div class="menu"></div>
<div class="menu"></div>
<div class="menu"></div>
<div class="profile-photo"></div>
<div class="profile-photo">'test check'</div>
const menuWrapper = document.querySelector('.menu-wrapper')
const test = document.createElement('div')
menuWrapper.append(test)
test.remove()
document.querySelector('.menu-wrapper').innerHTML = ''; // class가 .menu-wrapper인 엘리먼트 아래의 모든 엘리먼트를 지웁니다.
const menuWrapper = document.querySelector('.menu-wrapper');
while (menuWrapper.firstChild) {
menuWrapper.removeChild(menuWrapper.firstChild);
}
const menuWrapper = document.querySelector('.menu-wrapper');
while (menuWrapper.children.length > 3) {
menuWrapper.removeChild(menuWrapper.lastChild);
}
const menus = document.querySelectorAll('.menu')
menus.forEach(function(menu){
menus.remove();
})
// or
for (let menu of menus){
menu.remove()
}
그 외 알아야할 것 (자주 보면서 외우자)
Node 는 Element의 상위 개념이다.
자바스크립트 객체의 구조는 트리구조이다.
document.cloneNode 는, 생성하는 메소드가 아니라 복제하는 메소드
document.querySelector 는 , 생성하기 위한 메소드가 아니라 조회하는 메소드
document.importNode 는, template 을 활용하여 내용을 붙여넣을 때 사용하는 메소드
document.getElementsByTagName('div') tag이름이 div 인 element 여러 개를 조회
document.getElementById('div') id가 div 인 element 하나를 조회
document.getElementsByClassName('div') class가 div 인 element 여러 개를 조회
element.innerHTML = 'Hi' // element의 내용에 'Hi' 를 집어넣는다.
element.setAttribute('name', 'value') // name이 키, value 가 값이다. 예를 들어 div.setAttribute('class', 'username') 이렇게 들어가면
이미 삽입한 element 지우기
element.remove()
document.querySelector("#id").removeChild(element)
DOM이라는것을 처음 경험 했을 때가 계산기 만들 때 이미 만들어져있던 querySelector 였던거 같은데 이제 직접 사용하는걸 배우네... 이해하는데 한참 걸렸다. 최소 4번은 더 읽어봐야겠다.