HTML에 있는 태그(요소)를 JS에선 "문서객체"라고 부른다.
JS는 html의 요소들, 즉 문서객체들을 조작할 수 있다.
문서 객체를 조합해서 만들어낸 전체적인 형태를 "문서 객체 모델" (DOM, Document Object Model)이라고 한다.
문서 객체 조작은 JQuery, React 등의 라이브러리나 프레임워크로 더 쉬워졌다고한다.
document.addEventListener('DOMContentLoaded', () => {})
html에 head 태그 내부에 script를 배치하면 기본적으로 인식할 수 없음 = 출력 안됨
"DOMContentLoaded" 코드 사용 시, script 태그가 head 태그보다 위에 위치해도 코드가 실행된다.
예시:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Document</title>
<script>
document.addEventListener('DOMContentLoaded',() => {
const h1 = (text) => `<h1>${text}</h1>`
document.body.innerHTML += h1('1번째 script 태그')})
</script>
</head>
<body>
</body>
</html>
document.(읽어오고 싶은 구역)
코드 사용 시 문서의 바디 요소를 읽어올 수 있다.
document.querySelector(선택자)
html의 특정 구역 내에서, 1개의 요소를 호출할 경우에 사용된다.
선택자를 기입해서 해당 요소에 접근할 수 있는데, 이때 사용하는 선택자는 CSS 선택자이다.
선택자는 굉장히 여러 종류가 있기 때문에, CSS 선택자를 숙지하고 있는 것은 도움이 된다.
<script>
document.addEventListener('DOMContentLoaded', () => {
// DOM이 읽혀지자마자 해당 이벤트가 실행됩니다.
const header = document.querySelector('h1')
// h1 태그 자체를 이용해서 요소에 접근한다는 것을 변수 'header'에 담는다
header.textContent = 'HEADERS' // 'HEADERS'라는 텍스트를 생성한다.
header.style.color = 'white' // 텍스트의 컬러는 흰색으로 한다.
header.style.backgroundColor = 'black' // 텍스트에 검정색 배경을 준다
header.style.padding = '10px' // 패딩값을 준다
})
</script>
querySelector()
를 이용해서h1
하나에만 접근하였다.document.querySelectorAll(선택자)
내부 요소에 접근하기 위해 반복을 돌린다.
forEach()
메소드를 사용한다.<head>
<script>
document.addEventListener('DOMContentLoaded', () => {
const headers = document.querySelectorAll('h1')
// 여러개의 요소에 접근할 수 있도록 querySelectorAll 을 사용했고, h1 태그에 해당하는 요소들에 접근한다.
headers.forEach((header)) => {
// 디자인 속성은 윗 예시와 동일한데, forEach() 사용해서 여러개의 요소에 한번에 접근할 수 있다.
header.textContent = 'HEADERS'
header.style.color = 'white'
header.style.backgroundColor = 'black'
header.style.padding = '10px'
})
})
</script>
</head>
<body>
<h1></h1> // h1 태그를 사용하는 문서 객체가 여러개다.
<h1></h1> // <h1> 내부에 아무것도 없어도 <script>에서 입력한 내용이 대신 출력된다.
<h1></h1>
<h1></h1>
</body>
문서 객체.textContent
= 입력된 문자열을 그대로 넣는다.문서 객체.innerHTML
= 입력된 문자열을 html 형식으로 추가한다.<script>
document.addEventListener('DOMContentLoaded', () => {
const a = document.querySelector('#a')
const b = document.querySelector('#b')
// id 값을 이용해서 요소에 접근
a.textContent = '<h1>textContent 속성</h1>'
// 출력 시 ''안에 글자가 문자 그대로 표시 [<h1>textContent 속성</h1>]
b.innerHTML = '<h1>innerHTML 속성 </h1>'
//출력 시 ''안에 글자가 <h1>가 적용된 상태로 표시 innerHTML 속성 (해당 글자가 h1으로 변환)
</script>
<body>
<div id ="a"><div> // 해당 요소들의 id 값을 이용해서 접근했다.
<div id ="b"><div> // <div> 태그 내부엔 아무것도 적혀있지 않아도 <script>에 표시한 문자가 그대로 출력된다.
</body>
문서 객체.setAttribute(속성 이름, 값)
<script>
document.addEventListener('DOMContentLoaded', () => {
const link = document.querySelector('#abc')
// link라는 변수에 abc라는 id 값을 가진 문서 객체에 접근하는 경로를 할당했다.
link.setAttribute('href', 'https://velog.io/@hailey199535')
// link라는 변수에 담아져있던 객체의 속성 href의 값을 새로운 링크로 변경했다.
})
</script>
<body>
<p><a id="abc" href="#">My Velog</a></p>
//My Velog라는 문서 객체의 원래 href 값은 "#" 이었는데, 'https://velog.io/@hailey199535'로 속성값이 변경됐다.
</body>
문서 객체.getAttribute(속성 이름)
<script>
document.addEventListener('DOMContentLoaded',() => {
const href = document.querySelector('#abc')
// href 라는 변수에 abc라는 id 값을 가진 문서 객체에 접근하는 경로를 할당했다.
href.getAttribute('href')
// href가 접근한 요소의 속성 중 'href'라고 써있는 것을 가져온다.
document.write( '<p>href : ' + href + '</p>' );
// 그리고 변수 href가 접근해서 가져온 요소의 속성값을 html 내부에 기입한다.
})
</script>
</head>
<body>
<p><a id="abc" href="https://velog.io/@hailey199535"> My Velog</a></p>
// id 'abc'라는 요소의 href 속성 값인 "https://velog.io/@hailey199535" 부분을 추출
</body>
style
속성을 사용한다.style
의 속성은 객체이며, CSS로 입력할때랑 같은 값을 사용한다.<script>
document.addEventListener('DOMContentLoaded', () =>{
const divs = document.querySelectorAll('body > div')
// 여러개의 요소에 접근하기 때문에 querySelectorAll을 사용하고,
// body 하위에 있는 요소인 div 요소에 접근한다.
divs.forEach((div, index) => { // div의 개수가 25개이기 때문에, index는 자동으로 25번 돌게된다.
console.log(div, index)
const val = index*10 // 인덱스가 반복하기 때문에, 0부터 24까지 반복하면서 각 값에 100을 곱한다.
div.style.height = `10px`
div.style.backgroundColor = `rgba(${val}, ${val}, ${val})`
// val 이라는 변수에 계산된 값 (index*10)이 색을 정하는 값이 된다.
// 전체 출력 시 검정색으로 그라데이션이 생긴 요소들을 확인할 수 있다.
})
})
</script>
<body>
<div></div><div></div><div></div><div></div><div></div>
<div></div><div></div><div></div><div></div><div></div>
<div></div><div></div><div></div><div></div><div></div>
<div></div><div></div><div></div><div></div><div></div>
<div></div><div></div><div></div><div></div><div></div>
</body>
JS는 문서 객체에 접근 외 객체를 생성할 수도 있다.
문서 객체 생성 시, document.createElement()
메소드를 사용한다.
객체 생성 후, 어떤 문서 아래에 추가할지 지정해야 객체가 적용된다.
문서를 문서 아래 지정하는 것 = Tree
구조
상위 문서 객체 = 부모 객체
하위 문서 객체 = 자식 객체
부모 객체.appendChild(자식 객체)
메소드 사용 시 특정 부모 객체 아래 자식 객체 추가 가능
<script>
document.addEventListener('DOMContentLoaded', () => {
const header = document.createElement('h1') // header라는 변수를 이용해서 h1 태그를 생성한다.
header.textContent = '문서 객체 동적으로 생성하기' // h1 태그의 글 내용
header.setAttribute('data-custom', '사용자 정의 속성') // 사용자 정의 속성을 추가하고
header.style.color = 'white' // h1 글 색은 흰색으로,
header.style.backgroundColor = 'black' // h1 글의 배경색은 검정색으로 설정
document.body.appendChild(header) // 생성한 h1 태그를 body 아래에 자식 객체로 지정.
})
</script>
<body>
</body>
appendChild()
메소드는 문서 객체 이동시에도 사용setTimeout()
함수는 특정 시간 설정 시 해당 시간이 지나면 발생하는 함수<script>
document.addEventListener('DOMContentLoaded', () =>{
const divA = document.querySelector('#first')
//querySelector를 이용해서 id값이 first인 객체에 접근하고 이 객체를 변수 divA에 담음
const divB = document.querySelector('#second')
//querySelector를 이용해서 id값이 second인 객체에 접근하고 이 객체를 변수 divB에 담음
const h1 = document.createElement('h1')
// h1 태그 객체를 생성하고 h1이라는 변수에 담음
h1.textContent = '이동하는 태그' // 생성된 h1 태그의 내용물은 글자 '이동하는 태그'
const toFirst = () => {
divA.appendChild(h1)
setTimeout(toSecond, 5000)
}
// toFirst라는 변수에 함수를 담음
// 해당 함수는 divA라는 변수에 담겨있는 객체에 h1이란 변수에 담겨있는 객체를 집어넣음
// 그리고 이 함수는 5초 후 toSecond라는 변수에 담긴 함수를 호출함
const toSecond = () => {
divB.appendChild(h1)
setTimeout(toFirst, 5000)
// toSecondt라는 변수에 함수를 담음
// 해당 함수는 divB라는 변수에 담겨있는 객체에 h1이란 변수에 담겨있는 객체를 집어넣음
// 그리고 이 함수는 5초 후 toFirst라는 변수에 담긴 함수를 호출함
}
toFirst() // 그리고 일단 toFirst라는 변수에 담겨있는 함수를 먼저 실행
})
</script>
<body>
<div id = "first"> // 생성한 h1 태그는 이 div 객체의 자식 객체가 되었음
<h1>첫 번째 div 태그 내부</h1>
</div>
<hr>
<div id = "second">
// setTimeout() 함수로 인해, 기존 first div에 들어있던 h1 객체가 5초 후 해당 객체의 자식으로 변경
// 그리고 5초 후 다시 first div의 자식 객체로 변동
// 자식 객체는 하나의 부모 객체에만 담길 수 있기 때문에, 5초마다 글씨가 이동하는 효과가 일어남
<h1>두 번째 div 태그 내부</h1>
</div>
</body>
parentNode
속성으로 부모 객체에 접근할 수 있다.문서 객체.parentNode.removeChild(문서 객체)
<script>
document.addEventListener('DOMContentLoaded', () => {
setTimeout(() => { // 특정 시간 이후 실행되는 함수 실행
const h1 = document.querySelector('h1')
// h1 이라는 변수에 h1 태그를 담음
h1.parentNode.removeChild(h1)}, 3000)
// h1에 담겨있는 객체와 부모 객체와의 연결을 3초 후 해제
})
</script>
<body>
<h1>제거 대상 문서 객체</h1>
// 해당 h1은 body 태그라는 부모 객체의 자식 객체
// 브라우저에 html 실행 시, 3초 후 h1 태그에 있던 내용이 사라진다.
</body>
document.addEventListener('DOMContentLoaded', () => {})
의 의미는:<script>
document.addEventListener('DOMContentLoaded', () => {
let counter = 0 // 클릭 시 횟수를 재기 위해 counter 라는 변수를 두고 0 할당
const h1 = document.querySelector('h1') // h1 이라는 변수에 html에 있는 h1 문서 객체를 할당
h1.addEventListener('click', (event) => { // click 이라는 이벤트가 발생 했을 때,
counter++ // 변수 counter의 값이 1씩 증가하는 함수를 생성
h1.textContent = `클릭 횟수: ${counter}`
// click 이벤트가 발생할 주체는 h1이라는 변수에 담겨있는 객체의 text(내용)
// click 이벤트 발생 시, 증가된 counter의 값이 ${counter}에 담긴다.
})
})
</script>
<style>
h1{
user-select: none;
// 사용자가 더블 클릭을 하거나 드래그를 시도했을 때 해당 액션을 막는 용도
// 이 스타일로 인해 1번 클릭 시 횟수가 안정적으로 세어진다.
}
</style>
<body>
<h1>클릭 회수: 0</h1>
</body>
문서 객체.removeEventListener(이벤트 이름, 이벤트 리스너)
를 활용해서 제거할 수 있다.<script>
document.addEventListener('DOMContentLoaded', () => {
let counter = 0 // 클릭 시 횟수를 재기 위해 counter 라는 변수를 두고 0 할당
let isConnect = false // 이벤트 연결 여부를 위해 isConnect라는 변수를 두고 false 할당
const h1 = document.querySelector('h1')
// h1이라는 변수에 html에 있는 h1이라는 요소를 담음
const p = document.querySelector('p')
// p라는 변수에 html에 있는 p라는 요소 담음
const connectBtn = document.querySelector('#connect')
// connectBtn이라는 변수에 html에서 id값이 connect인 요소 담음
const disconnectBtn = document.querySelector('#disconnect')
// disconnectBtn이라는 변수에 html에서 id값이 disconnect인 요소 담음
const listener = (event) => { // listener라는 변수에 이벤트 발생 시 실행되는 함수 할당
counter++
// 이벤트 실행 횟수만큼 counter의 값 증가
h1.textContent = `클릭 횟수: ${counter}`
// counter의 값이 변수 h1에 있는 객체의 내용에 대입됨
}
connectBtn.addEventListener('click', () => {
// connectBtn이라는 변수에 담긴 객체에 이벤트 리스너 추가
// 클릭 이벤트 발생 시 함수 실행
if (isConnect === false){ // 만약 connectBtn에서 이벤트 실행 시 isConnect의 상태가 false라면,
h1.addEventListener('click', listener)
// h1이라는 변수에 담겨있던 객체에 click 이벤트 발생 시 listener라는 함수가 실행됨
p.textContent = '이벤트 연결 상태: 연결'
// 함수 실행 시, p라는 변수에 담겨있던 요소의 내용이 '이벤트 연결 상태: 연결' 로 변경
isConnect = true
// 함수 실행 시, isConnect의 상태는 true가 된다.
}
})
disconnectBtn.addEventListener('click', () =>{
// disconnectBtn이라는 변수에 담긴 객체에 이벤트 리스너 추가
// 클릭 이벤트 발생 시 함수 실행
if(isConnect === true){ // 만약 disconnectBtn에서 이벤트 실행 시 isConnect의 상태가 true라면,
h1.removeEventListener('click', listener)
// h1이라는 변수에 담겨있던 객체에 click 이벤트 발생 시 listener라는 함수가 제거됨
p.textContent = '이벤트 연결 상태: 해제'
// 함수 실행 시, p라는 변수에 담겨있던 요소의 내용이 '이벤트 연결 상태: 해제' 로 변경
isConnect = false
// 함수 실행 시, isConnect의 상태는 false가 된다.
}
})
})
</script>
<style>
h1{
user-select: none;
}
</style>
<body>
<h1>클릭 횟수: 0</h1> // h1이라는 변수에 담겨지는 html의 요소
<button id="connect">이벤트 연결</button> // connectBtn이라는 변수에 담겨지는 html의 요소
<button id="disconnect">이벤트 제거</button> // disconnectBtn이라는 변수에 담겨지는 html의 요소
<p>이벤트 연결 상태: 해제</p> // p라는 변수에 담겨지는 html의 요소
</body>
드디어 정리가 끝났다!
내용이 어려웠다기보단 코드 해석에 주석을 다는 작업이 길었다.
마침 노마드코더에서 들었던 강의와 맞물리는 부분이 많아서 공부 자체는 어렵지 않았었다.
이제 곧 리액트 공부가 시작된다...
아직 자바스크립트도 아주 기초만 아는데 내가 할 수 있을까?
못하면 어쩔려나 그냥 해야하는데!
걱정은 미리 하지말고 그냥 공부나 열심히 하자... 오늘도 내 몸엔 버섯이 자란다.... 🍄
출처: 혼자 공부하는 자바스크립트 (한빛미디어)