Index
Index9. DOM (Document Object Model)9.1 DOM ์ด๋?9.2 DOM ํธ๋ฆฌ์ ์ ๊ทผํ๊ธฐ9.3 DOM ์ ์ด ๋ช
๋ น์ด9.4 ์ด๋ฒคํธ ๊ฐ์ฒด9.5 ์ด๋ฒคํธ ํ๋ฆ9.6 ์ด๋ฒคํธ target, currentTarget9.7 ์ด๋ฒคํธ ์์9.8 ์ด๋ฒคํธ์ this9.9 ์ค์ต
ย
9. DOM (Document Object Model)
9.1 DOM ์ด๋?
DOM ์ HTML ๋ฌธ์์ ๋ด์ฉ์ ํธ๋ฆฌํํ๋ก ๊ตฌ์กฐํํ์ฌ ์นํ์ด์ง์ ํ๋ก๊ทธ๋๋ฐ ์ธ์ด๋ฅผ ์ฐ๊ฒฐ์์ผ์ฃผ๋ ์ญํ ์ ํฉ๋๋ค. ์ด๋ ๊ฐ๊ฐ์ ์์์ ์์ฑ, ์ฝํ
์ธ ๋ฅผ ํํํ๋ ๋จ์๋ฅผ '๋
ธ๋(node)'๋ผ๊ณ ํฉ๋๋ค.
ย
ย
9.2 DOM ํธ๋ฆฌ์ ์ ๊ทผํ๊ธฐ
document ๊ฐ์ฒด๋ฅผ ํตํด HTML ๋ฌธ์์ ์ ๊ทผ์ด ๊ฐ๋ฅํฉ๋๋ค. document๋ ๋ธ๋ผ์ฐ์ ๊ฐ ๋ถ๋ฌ์จ ์นํ์ด์ง๋ฅผ ๋ํ๋ด๋ฉฐ, DOM ํธ๋ฆฌ์ ์ง์
์ ์ญํ ์ ์ํํฉ๋๋ค.
// ํด๋นํ๋ Id๋ฅผ ๊ฐ์ง ์์์ ์ ๊ทผํ๊ธฐ document.getElementById() // ํด๋นํ๋ ๋ชจ๋ ์์์ ์ ๊ทผํ๊ธฐ document.getElementsByTagName(); // ํด๋นํ๋ ํด๋์ค๋ฅผ ๊ฐ์ง ๋ชจ๋ ์์์ ์ ๊ทผํ๊ธฐ document.getElementsByClassName(); // css ์ ํ์๋ก ๋จ์ผ ์์์ ์ ๊ทผํ๊ธฐ document.querySelector("selector"); // css ์ ํ์๋ก ์ฌ๋ฌ ์์์ ์ ๊ทผํ๊ธฐ document.querySelectorAll("selector");
ย
ย
9.3 DOM ์ ์ด ๋ช ๋ น์ด
ย
- ์ด๋ฒคํธ ์ฝ์
target.addEventListener( type, listener )
์ ๋ฌธ๋ฒ ํํ๋ฅผ ์ง๋๋๋ค.<button>HELLO!</button>
// ์ด๋ฒคํธ์ ํ์ ์๋ click, mouseover, mouseout, wheel ๋ฑ ๋ค์ํ ์ด๋ฒคํธ๋ฅผ ๊ฐ์งํฉ๋๋ค. // listener ํจ์์ ์ธ์์๋ ์ด๋ฒคํธ์ ๋ํ ์ ๋ณด๊ฐ ๋ด๊ฒจ์์ต๋๋ค. const myBtn = document.querySelector("button"); myBtn.addEventListener('click', function(){ console.log("hello world"); })
ย
- ํด๋์ค ์ ์ด
DOM api๋ฅผ ํตํด ์์์ class ์์ฑ์ ์ ์ดํ ์ ์์ต๋๋ค.
<button>Make me BLUE!</button>
const myBtn = document.querySelector("button"); myBtn.addEventListener('click', function(){ // blue ๋ผ๋ ํด๋์ค์ ์์ฑ ๊ฐ์ ์ง์ ํ ์ ์์ต๋๋ค. myBtn.classList.add("blue"); // myBtn.classList.remove(โblueโ); ํด๋์ค๋ฅผ ์ ๊ฑฐํฉ๋๋ค. // myBtn.classList.toggle(โblueโ); ํด๋์ค๋ฅผ ํ ๊ธํฉ๋๋ค. ์์ผ๋ฉด ๋ฃ์ด์ฃผ๊ณ , ์์ผ๋ฉด ์ ๊ฑฐํฉ๋๋ค. // myBtn.classList.contains(โblueโ); ํด๋นํ๋ ํด๋์ค๊ฐ ์๋์ง ํ์ธํฉ๋๋ค. })
ย
- ์์ ์ ์ด
DOM api๋ฅผ ์ด์ฉํ๋ฉด ์์๋ฅผ ์๋กญ๊ฒ ์์ฑํ๊ณ , ์์นํ๊ณ , ์ ๊ฑฐํ ์ ์์ต๋๋ค.
<ul></ul> <button>Make me MORE!</button>
// document.createElement(target); target ์์๋ฅผ ์์ฑํฉ๋๋ค. // document.createTextNode(target); target ํ ์คํธ๋ฅผ ์์ฑํฉ๋๋ค. // element.appendChild(target); target ์์๋ฅผ element์ ์์์ผ๋ก ์์นํฉ๋๋ค. // element.removeChild(target); element์ target ์์ ์์๋ฅผ ์ ๊ฑฐํฉ๋๋ค. const myBtn = document.querySelector(โbuttonโ); const myUl = document.querySelector(โulโ); myBtn.addEventListener(โclickโ, function(){ for(let i=0; i < 5; i++){ const myLi = document.createElement(โliโ); myUl.appendChild(myLi); } })
<div id="parentElement"> <span id="childElement">hello guys~</span> </div>
// parentElement.insertBefore(target, location); target์์๋ฅผ element์ ์์์ธ location ์์น๋ก ์ด๋ํฉ๋๋ค. var span = document.createElement("span"); var sibling = document.getElementById("childElement"); var parentDiv = document.getElementById("parentElement"); parentDiv.insertBefore(span, sibling);
ย
- JavaScript ๋ฌธ์์ด์ ์ฌ์ฉํด element, text ๋ ธ๋๋ฅผ ์์ฑํ๊ฑฐ๋ ์ถ๊ฐํ๊ธฐ
DOM api๋ฅผ ์ด์ฉํ๋ฉด ์์ ์์ ๊ฐ์ ์ ๊ทผํ์ฌ ๊ฐ์ ๊ฐ์ ธ์ค๊ฑฐ๋, ๋ณ๊ฒฝํ ์ ์์ต๋๋ค.
<p></p> <input type="text"> <button>Write Something!</button>
const myBtn = document.querySelector("button"); const myP = document.querySelector("p"); const myInput = document.querySelector("input"); myBtn.addEventListener('click', function(){ myP.textContent = myInput.value; }); // input ์์์ 'input' ์ด๋ฒคํธ๋ฅผ ์ฐ๊ฒฐํ๋ฉด ์ค์๊ฐ์ผ๋ก ๊ฐ์ด ๋ฐ์๋๊ฒ ๋ง๋ค ์๋ ์์ต๋๋ค. myInput.addEventListener('input', ()=>{ myP.textContent = myInput.value; }); myP.innerHTML = "<strong>I'm Strong!!</strong>"; myP.outerHTML = "<div></div>"; // innerHTML ์ ์์(element) ๋ด์ ํฌํจ ๋ HTML ๋งํฌ์ ์ ๊ฐ์ ธ์ค๊ฑฐ๋ ์ค์ ํฉ๋๋ค. // innerText ์์ฑ์ ์์์ ๊ทธ ์์์ ๋ ๋๋ง ๋ ํ ์คํธ ์ฝํ ์ธ ๋ฅผ ๋ํ๋ ๋๋ค. (innerText๋ "์ฌ๋์ด ์ฝ์ ์ ์๋" ์์๋ง ์ฒ๋ฆฌํฉ๋๋ค.) // textContent ์์ฑ์ ๋ ธ๋์ ํ ์คํธ ์ฝํ ์ธ ๋ฅผ ํํํฉ๋๋ค.
ย
** innerHTML ์ฌ์ฉ์ ์ฃผ์ ์ฌํญ : https://developer.mozilla.org/ko/docs/Web/API/Element/innerHTML#security_considerations
** innerText ์ textContent์ ์ฐจ์ด : https://developer.mozilla.org/ko/docs/Web/API/HTMLElement/innerText#์์
ย
๋ ์ ๋ฐํ๊ฒ ๋ฐฐ์นํ๊ธฐ
<strong class="sayHi"> ๋ฐ๊ฐ์ต๋๋ค. </strong>
const sayHi = document.querySelector('.sayHi'); sayHi.insertAdjacentHTML('beforebegin', '<span>์๋ ํ์ธ์ ์ ๋</span>'); sayHi.insertAdjacentHTML('afterbegin', '<span>์ฌํ์ ๋๋ค</span>'); sayHi.insertAdjacentHTML('beforeend', '<span>๋ฉด์ ์ค์๋ฉด</span>'); sayHi.insertAdjacentHTML('afterend', '<span>์นํจ์ฌ๋๋ฆด๊ฒ์</span>');
ย
ย
- DOM ์์์ ๋ ธ๋ ํ์ํ๊ธฐ
<!-- ์ฃผ์์ ๋๋ค ์ฃผ์. --> <article class="cont"> <h1>์๋ ํ์ธ์ ์ ๋ ์ด๋ฐ ์ฌ๋์ ๋๋ค.</h1> <p>์ง๊ธ๋ถํฐ ์๊ธฐ์๊ฐ ์ฌ๋ฆฌ๊ฒ ์ต๋๋ค</p> Lorem ipsum dolor sit amet consectetur adipisicing elit. Deserunt incidunt voluptates laudantium fugit, omnis dolore itaque esse exercitationem quam culpa praesentium, quisquam repudiandae aut. Molestias qui quas ea iure officiis. <strong>๊ฐ์ฌํฉ๋๋ค!</strong> </article>
const cont = document.querySelector(".cont"); console.log(cont.firstElementChild); // ์ฒซ๋ฒ์งธ ์์์ ์ฐพ์ต๋๋ค. console.log(cont.lastElementChild); // ๋ง์ง๋ง ์์์ ์ฐพ์ต๋๋ค. console.log(cont.nextElementSibling); // ๋ค์ ํ์ ์์๋ฅผ ์ฐพ์ต๋๋ค. console.log(cont.previousSibling); // ์ด์ ํ์ ์์๋ฅผ ์ฐพ์ต๋๋ค. console.log(cont.children); // ๋ชจ๋ ์ง๊ณ์์์ ์ฐพ์ต๋๋ค. console.log(cont.parentElement); // ๋ถ๋ชจ ์์๋ฅผ ์ฐพ์ต๋๋ค.
ย
9.4 ์ด๋ฒคํธ ๊ฐ์ฒด
์ด๋ฒคํธ์์ ํธ์ถ๋๋ ํธ๋ค๋ฌ์๋ ์ด๋ฒคํธ์ ๊ด๋ จ๋ ๋ชจ๋ ์ ๋ณด๋ฅผ ๊ฐ์ง๊ณ ์๋ ๋งค๊ฐ๋ณ์๊ฐ ์ ์ก๋ฉ๋๋ค. ์ด๊ฒ์ด ๋ฐ๋ก ์ด๋ฒคํธ ๊ฐ์ฒด์
๋๋ค!
<article class="parent"> <ol> <li><button class="btn-first" type="button">๋ฒํผ1</button></li> <li><button type="button">๋ฒํผ2</button></li> <li><button type="button">๋ฒํผ3</button></li> </ol> </article>
const btnFirst = document.querySelector('.btn-first'); btnFirst.addEventListener('click', (event) => { console.log(event); });
ย
9.5 ์ด๋ฒคํธ ํ๋ฆ
๋ธ๋ผ์ฐ์ ํ๋ฉด์์ ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ๋ฉด ๋ธ๋ผ์ฐ์ ๋ ๊ฐ์ฅ ๋จผ์ ์ด๋ฒคํธ ๋์์ ์ฐพ๊ธฐ ์์ํฉ๋๋ค.
์ด๋ฒคํธ ๋์์ ์ฐพ์๊ฐ ๋ ๊ฐ์ฅ ์์์ window ๊ฐ์ฒด๋ถํฐ document, body ์์ผ๋ก DOM ํธ๋ฆฌ๋ฅผ ๋ฐ๋ผ ๋ด๋ ค๊ฐ๋๋ค. ์ด๋ฅผ ์บก์ฒ๋ง ๋จ๊ณ๋ผ๊ณ ํฉ๋๋ค. ์ด๋ ์ด๋ฒคํธ ๋์์ ์ฐพ์๊ฐ๋ ๊ณผ์ ์์ ๋ธ๋ผ์ฐ์ ๋ ์ค๊ฐ์ ๋ง๋๋ ๋ชจ๋ ์บก์ฒ๋ง ์ด๋ฒคํธ ๋ฆฌ์ค๋๋ฅผ ์คํ์ํต๋๋ค. ๊ทธ๋ฆฌ๊ณ ์ด๋ฒคํธ ๋์์ ์ฐพ๊ณ ์บก์ฒ๋ง์ด ๋๋๋ฉด ๋ค์ DOM ํธ๋ฆฌ๋ฅผ ๋ฐ๋ผ ์ฌ๋ผ๊ฐ๋ฉฐ ๋ง๋๋ ๋ชจ๋ ๋ฒ๋ธ๋ง ์ด๋ฒคํธ ๋ฆฌ์ค๋๋ฅผ ์คํํฉ๋๋ค. ์ด๋ฅผ ์ด๋ฒคํธ ๋ฒ๋ธ๋ง ๋จ๊ณ๋ผ๊ณ ํฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ ์ด๋ฌํ ๊ณผ์ ์์ ์ด๋ฒคํธ ๋ฆฌ์ค๋๊ฐ ์ฐจ๋ก๋ก ์คํ๋๋๊ฒ์ ์ด๋ฒคํธ ์ ํ(event propagation)๋ผ๊ณ ํฉ๋๋ค.
<!DOCTYPE html> <html lang="ko"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <link rel="stylesheet" href="../reset.css"> <style> </style> </head> <body> <article class="parent"> <button class="btn" type="button">๋ฒํผ</button> </article> <script> const parent = document.querySelector('.parent'); const btnFirst = document.querySelector('.btn'); btnFirst.addEventListener('click', (event) => { console.log("btn capture!"); }) window.addEventListener('click', () => { console.log("window capture!"); }, true); // true : ์บก์ฒ๋ง ๋จ๊ณ์ ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ๋๋ก ํฉ๋๋ค. document.addEventListener('click', () => { console.log("document capture!"); }, true); parent.addEventListener('click', () => { console.log("parent capture!"); }, true); btnFirst.addEventListener('click', (event) => { console.log("btn bubble!"); }) parent.addEventListener('click', () => { console.log("parent bubble!"); }); document.addEventListener('click', () => { console.log("document bubble!"); }); window.addEventListener('click', () => { console.log("window bubble!"); }); </script> </body> </html>
ย
ย
9.6 ์ด๋ฒคํธ target, currentTarget
์ด๋ฌํ ์ด๋ฒคํธ์ ํน์ง ๋๋ถ์ ์ด๋ฒคํธ ๊ฐ์ฒด์๋ target, currentTarget ์ด๋ผ๋ ์์ฑ์ด ์กด์ฌํฉ๋๋ค. target ์์ฑ์๋ ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ ์ง์์ง์ ์ ๋ณด๊ฐ ๋ด๊ฒจ ์์ต๋๋ค. target ์์ฑ์ ํตํด ์ด๋ฒคํธ ๋ฆฌ์ค๋๊ฐ ์๋ ์์์ ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ์ ๋๋ ํด๋น ์์์ ์ ๊ทผ ํ ์ ์์ต๋๋ค.
currentTarget ์์ฑ์๋ ์ด๋ฒคํธ ๋ฆฌ์ค๋๊ฐ ์ฐ๊ฒฐ๋ ์์๊ฐ ์ฐธ์กฐ๋์ด ์์ต๋๋ค.
<article class="parent"> <ol> <li><button class="btn-first" type="button">๋ฒํผ1</button></li> <li><button type="button">๋ฒํผ2</button></li> <li><button type="button">๋ฒํผ3</button></li> </ol> </article> <script> const parent = document.querySelector('.parent'); parent.addEventListener('click', function (event) { console.log(event.target); console.log(event.currentTarget); }) </script>
ย
9.7 ์ด๋ฒคํธ ์์
์์์ ์ฐ๋ฆฌ๋ ์ด๋ฒคํธ์ ํ๋ฆ์ ํตํด ์ด๋ฒคํธ ๋ฆฌ์ค๋๊ฐ ์๋ ์์์ ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ์ ๋๋ ํด๋น ์์์ ์ ๊ทผ ํ ์ ์๋ค๋ ๊ฒ์ ์๊ฒ ๋์์ต๋๋ค. ์ด๋ฅผ ์ด์ฉํด ์ด๋ฒคํธ ๋ฆฌ์ค๋๊ฐ ์์ด๋ ๋ง์น ๋ฆฌ์ค๋๊ฐ ์๋ ๊ฒ ์ฒ๋ผ ์ฌ์ฉ ํ ์ ์์ต๋๋ค.
<!DOCTYPE html> <html lang="ko"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <link rel="stylesheet" href="../reset.css"> <style> </style> </head> <body> <article class="parent"> <ol> <li><button class="btn-first" type="button">๋ฒํผ1</button></li> <li><button type="button">๋ฒํผ2</button></li> <li><button type="button">๋ฒํผ3</button></li> </ol> </article> <script> const parent = document.querySelector('.parent'); parent.addEventListener('click', function (event) { console.log(event.target); if (event.target.nodeName === "BUTTON") { event.target.innerText = "๋ฒํผ4"; } }) </script> </body> </html>
์ด๋ฌํ ํ
ํฌ๋์ ์ด๋ฒคํธ ์์์ด๋ผ๊ณ ํฉ๋๋ค.
ย
9.8 ์ด๋ฒคํธ์ this
์ด๋ฒคํธ ๋ฆฌ์ค๋ ํจ์ ๋ด๋ถ์์์ this ๊ฐ์ ์ด๋ฒคํธ๊ฐ ์ฐ๊ฒฐ๋ ๋
ธ๋๋ฅผ ์ฐธ์กฐํฉ๋๋ค.
<article class="parent"> <ol> <li><button class="btn-first" type="button">๋ฒํผ1</button></li> <li><button type="button">๋ฒํผ2</button></li> <li><button type="button">๋ฒํผ3</button></li> </ol> </article> <script> const parent = document.querySelector('.parent'); parent.addEventListener('click', function (event) { console.log(this); }) </script>
์ด๋ event.currentTarget ์์ฑ์ ์ฐธ์กฐ๊ฐ๊ณผ ์ ์ฌํฉ๋๋ค.
๋ง์ฝ ์ด๋ฒคํธ ๋ฆฌ์ค๋ ํจ์๋ฅผ ํ์ดํ ํจ์๋ก ์ด๋ค๋ฉด this ๊ฐ ๊ฐ๋ฆฌํค๋ ๋์์ด ๋ฌ๋ผ์ง๋ค๋ ์ ์ ์ ์ํ์ธ์.
ย
9.9 ์ค์ต
<!DOCTYPE html> <html lang="ko"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <link rel="stylesheet" href="reset.css"> <style> /* ์ง์ ์ ๋ ํธ ๋ฐ์ค ๋ง๋ค๊ธฐ */ h2 { margin: 30px; } .cont-select { position: relative; width: 200px; } .btn-select { width: 100%; padding: 13px 14px; color: #000; font-size: 12px; line-height: 14px; text-align: left; border: 1px solid #C4C4C4; box-sizing: border-box; border-radius: 10px; cursor: pointer; background: url("images/icon-Triangle-down.png") right 13px center no-repeat; /* ๋ง์ค์ ์ถ๊ฐ */ white-space: nowrap; text-overflow: ellipsis; overflow: hidden; } .btn-select:focus { outline: 3px solid #F8E4FF; } .list-member { display: none; width: 100%; overflow: hidden; position: absolute; left: 0; top: 51px; background: #FFF; border: 1px solid #C4C4C4; box-shadow: 4px 4px 14px rgba(0, 0, 0, 0.15); border-radius: 10px; } .btn-select.on { background: url("images/icon-Triangle-up.png") right 13px center no-repeat; } .btn-select.on+.list-member { display: block; } .list-member li { height: 40px; padding: 5px 18px; } .list-member li button { display: block; height: 30px; width: 100%; border: none; background-color: #fff; border-radius: 8px; cursor: pointer; /* ๋ง์ค์ ์ถ๊ฐ */ white-space: nowrap; text-overflow: ellipsis; overflow: hidden; } .list-member li button:focus, .list-member li button:hover { background-color: #F8E4FF; } </style> </head> <body> <h2>์ ๋ ํธ ๋ฐ์ค ๋ง๋ค๊ธฐ</h2> <article class="cont-select"> <button class="btn-select">๋์ ์ต์ ํ๋ก๊ทธ๋๋ฐ ์ธ์ด</button> <ul class="list-member"> <!-- <li><button type="button">Python</button></li> <li><button type="button">Java</button></li> <li><button type="button">JavaScript</button></li> <li><button type="button">C#</button></li> <li><button type="button">C/C++</button></li> --> </ul> </article> </body> </html>
ย