DOM (Document Object Model)은 자바스크립트와 웹 브라우저 환경에서 웹 페이지와 사용자 간의 상호작용을 가능하게 하는 요소로서 활용되는데요.
자바스크립트의 꽃은 DOM이라는 말이 있을 정도로 DOM은 JS에서 굉장히 중요한 요소이며, 이러한 DOM을 문서의 구조를 트리 형태로 표현하여 프로그래밍 언어가 문서의 내용과 구조를 조작할 수 있게 합니다.
DOM은 JS에서 웹 브라우저의 각 태그 요소들을 조작하게 해주는 트리인 만큼 DOM을 이용해 해당 HTML의 요소들을 접근하는 방법 또한 다양하게 존재하는데요. 주요 접근법들은 다음과 같습니다.
접두사 get으로 이루어진 메서드들을 활용하는 방법으로, 크게 아이디(ById), 태그(ByTagName), 클래스(ByClassName)이 존재합니다.
// id는 각각 고유하므로 하나의 반환값을 가짐 document.getElementById( "아이디" ) // 태그와 클래스는 여러개 일 수 있으므로 1개 이상의 반환값을 가짐 document.getElementsByTagName( "태그" ) document.getElementsByClassName( "클래스" )
접두사 query로 이루어진 메서드들을 활용하는 방법으로, 크게 단수와 복수로 선택 가능하며, 이때 선택자 기호를 필수로 붙여줘야 합니다.
//아이디가 id인 요소를 선택 (모든 요소들의 단수 선택 가능) document.querySelector( "#id" ) // 클래스가 공통적으로 존재하는 요소들을 선택 (모든 요소들의 복수 선택 가능) document.querySelectorAll( ".input_box")
get과 query를 이용해 요소를 선택하는 것은 겉으로 봤을때는 큰 차이점이 없는데요. 단 두 요소의 반환 타입이 다르다는 점, 그로 인해 사용할 수 있는 메서드의 있고 없고의 차이가 꽤 크다는 점이 차이점이라고 할 수 있겠습니다.
특히 두 정보들 둘 다 배열 형태로 반환 받는데요. get은 HTMLCollection으로, query는 NodeList 형태로 제공 받으며, 배열의 특성으로 인해 get 접근법을 이용해서 정보들을 가져올 경우 JS 고유의 배열 메서드는 사용 불가능합니다. (물론 NodeList 형태의 배열일 경우엔 JS 배열 메서드들을 사용 가능)
DOM을 이용해 HTML의 특정 태그에 텍스트를 생성하는 방법은 크게 두 가지 방법이 존재하는데요. 하나는 선택된 태그에 innerHTML 프로퍼티로 문자를 전달하거나, value 속성의 값으로 전달(단일 태그의 경우 해당)하는 방법이 있고, textContent 메서드를 이용하여 기존의 문자열을 수정할 수도 있으며, createTextNode를 이용해 새로운 텍스트 노드를 만들어 다른 태그의 하위 노드로 붙여 사용할 수 있습니다.
또 한 태그 생성법은 주로 createElement 메서드를 사용하는데, 생성할 태그를 문자열로 전달한 뒤 변수에 저장하여 사용합니다.
// id가 h1인 요소 선택 let h1 = document.getElementById("h1"); // 선택된 h1의 태그의 innerHTML 프로퍼티(화면에 보여지는 텍스트)를 hello로 지정합니다. h1.innerHTML = "hello"; // h2 요소를 생성합니다. let h2 = document.createElement('h2'); // 텍스트 콘텐츠를 설정합니다. h2.textContent = "반갑습니다"; // h2 요소를 부모인 body의 자식(appendChild)으로 추가합니다. document.body.appendChild(h2); // <h3> 요소 생성 let h3 = document.createElement('h3'); // 텍스트 노드 생성 let textNode = document.createTextNode('오하요!'); // 텍스트 노드를 <h3> 요소에 추가 h3.appendChild(textNode); // <h3> 요소를 문서의 <body>에 추가 document.body.appendChild(h3);
// 과일 배열 생성 const fruits = ['apple', 'banana', 'orange', 'kiwi', 'mango']; //ul 생성 후 속성 달기 let ulTag = document.createElement('ul') ulTag.setAttribute('id', 'list') // foreach를 이용해 fruits 배열의 값들 하나 하나로 li 만들어 어펜드하기 fruits.forEach( fruit => { let liElement = document.createElement('li'); // let fName = document.createTextNode( fruit ); // liElement.appendChild(fName); // document.getElementById('list').appendChild(liElement); });
태그에 속성을 추가하는 방법은 크게 두 가지가 존재하는데요. 하나는 기존에 이미 존재하는 태그의 속성에 값을 지정하거나 수정하는 것이고, 또 하나는 새로운 속성을 만들어 사용하는 것으로, 이때 닷 노테이션과 setAttribute 메서드를 사용하는 사용합니다.
HTML 코드
<body> <video src="" id="video" controls="true"></video> <br /> </body>
JS 코드
// 요소를 선택한 후 메서드로 속성과 값(경로)를 지정 document.getElementById("video").setAttribute("src", "./고민시.mp4"); // 새로운 요소를 만들고 속성을 추가 let imgElement = document.createElement("img"); // 경로 속성 imgElement.src = "./고민시.png"; // 사진이 안보일 경우 대체 텍스트 속성 imgElement.alt = "고민시"; // 높이 속성 imgElement.width = 500; document.body.appendChild(imgElement);
스타일의 경우 세 가지 지정법이 존재하는데요. 닷 노테이션(.)으로 지정하는 방법이 있고,대괄호를 이용해 스타일을 지정하는 방법, 이렇게 존재합니다.
이때 font-family, font-size와 같이 하이폰(-)으로 연결된 이름의 속성의 경우 닷 노테이션을 사용할 때에는 하이폰을 제거한 후 둘째 단어의 첫 글자를 대문자로(fontFamily, fontSize등) 표기를 해야하며,
대괄호로 해당 속성을 지정할 경우 평소 css 스타일을 주는 것 처럼 하이폰을 포함해 작성하시면 됩니다.
HTML 코드
<body> <h1 id="heading">DOM</h1> <div id="box"> <p>Document</p> <p>Object</p> <p>Model</p> </div> </body>
JS 코드
// 속성을 그대로 사용하는 경우 ( 하이픈 없이 단어 하나로 구성된 속성들 ) // 닷 노테이션(.) 사용 const h1 = document.querySelector('#heading'); h1.style.color = 'red'; h1.style.width = '400px'; h1.style.height = '100px'; h1.style.background = 'pink'; h1.style.border = '1px solid black'; // 두 가지 이상의 속성이 하이픈으로 연결된 경우 하이픈을 제거하고, camelCase 형식으로 변경 // 닷 노테이션(.) 사용 const box = document.getElementById('box'); box.style.fontFamily = '궁서'; box.style.fontSize = '20px'; box.style.fontWeight = 'bold'; // 대괄호([]) 표기법 사용 const pList1 = document.querySelectorAll('p'); // NodeList const pList2 = document.getElementsByTagName('p'); // HTMLCollection // HTMLCollection 객체에는 forEach() 메소드가 없기 때문에 사용할 수 없다. // 즉 공통된 태그들의 값을 배열로 얻어와 JS 내장 배열 메서드를(forEach, map등)을 사용하려면 querySelectorAll() 를 사용하면 된다. pList1.forEach( p => { p.style['color'] = 'red'; p.style['background-color'] = 'yellow'; });
요소 삭제의 경우 주로 부모에서 자식 요소를 제거하는 removeChild 메서드와 해당 요소 자체를 삭제하는 remove 메서드가 있습니다.
부모에서 자식 요소 제거하기
<!DOCTYPE html> <html lang="ko"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>removeChild 예제</title> </head> <body> <div id="parent"> <p id="child1">안녕하세요!</p> <p id="child2">반갑습니다!</p> </div> <script> var parent = document.getElementById("parent"); var child = document.getElementById("child1"); parent.removeChild(child); </script> </body> </html>
해당 요소를 직접 삭제하기
<!DOCTYPE html> <html lang="ko"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>remove 예제</title> </head> <body> <p id="child1">안녕하세요!</p> <p id="child2">반갑습니다!</p> <script> var child = document.getElementById("child1"); child.remove(); </script> </body> </html>
해당 예제는 DOM 요소를 직접 만들고 메서드를 이용해 속성을 1초마다 부여하는 예제입니다. 주석은 달지 않도록 하겠습니다. (코드를 천천히 보시면서 이해해 보세요!)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <style> #box{ width: 100px; height: 100px; color: white; background-color: red; text-align: center; display: table-cell; vertical-align: middle; } #text{ font-size: 2rem; font-weight: bold; } </style> <script defer> window.onload = function(){ let i = 0; let colors = ["red", "orange", "yellow", "green", "blue", "navy", "purple"]; let contents = ["빨", "주", "노", "초", "파", "남", "보"]; let box = document.querySelector("#box") let text = document.querySelector("#text") const changeColors = function() { setInterval(() => { box.style['background'] = colors[i]; text.textContent = contents[i]; i++ if(i == 7) i = 0; }, 1000); }; changeColors() }; </script> <title>Document</title> </head> <body> <div id = "box"> <p id = "text">빨</p> </div> </body> </html>