[JavaScript 14] 문서 객체 조작하기

김헤일리·2022년 11월 25일
0

JavaScript

목록 보기
15/20

문서 객체란?

  • HTML에 있는 태그(요소)를 JS에선 "문서객체"라고 부른다.

    • html, heas, body, title, h1, div, span 등
  • JS는 html의 요소들, 즉 문서객체들을 조작할 수 있다.

  • 문서 객체를 조합해서 만들어낸 전체적인 형태를 "문서 객체 모델" (DOM, Document Object Model)이라고 한다.

  • 문서 객체 조작은 JQuery, React 등의 라이브러리나 프레임워크로 더 쉬워졌다고한다.


1. DOMContentLoaded 이벤트

  • 문서 객체 조작 시 사용하는 코드
  • document.addEventListener('DOMContentLoaded', () => {})
    • html에 head 태그 내부에 script를 배치하면 기본적으로 인식할 수 없음 = 출력 안됨

    • "DOMContentLoaded" 코드 사용 시, script 태그가 head 태그보다 위에 위치해도 코드가 실행된다.

      • "DOMContentLoaded"는 html에 있는 DOM Tree를 전부 파악하자마자 바로 실행된다.
    • 예시:

<!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>
  • "DOMContentLoaded" 이벤트는 브라우저가 문서 객체를 전부 읽고나서 실행된다.


2. 문서 객체 가져오기

  • document.(읽어오고 싶은 구역) 코드 사용 시 문서의 바디 요소를 읽어올 수 있다.

    • document.body, head, title 등
    • 하지만 특정 구역 내부에 있는 요소들은 또 다른 방식으로 불러와야 한다.

❗️ 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 하나에만 접근하였다.
  • 그리고 해당 요소에 접근한 후, 들어갈 내용, 글자색, 배경색 등을 변경했다. (요소에 참견함)
    • 실제로 "body" 태그 사이에 "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>


3. 글자 조작하기

  • html 내부에 있는 글자를 조작하는 방법은 두가지가 있다.
    • 문서 객체.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>


4. 속성 조작하기

  • 문서 객체의 속성을 조작할 때 사용하는 메소드가 따로 있다.

❗️ 문서 객체.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>


5. 스타일 조작하기

  • 문서 객체의 스타일을 조작할 땐 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>


6. 문서 객체 생성하기

  • 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>


7. 문서 객체 이동하기

  • 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>


8. 문서 객체 제거하기

  • 이미 연결된 자식 객체를 제거하기 위해선 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>


9. 이벤트 설정하기

❗️ addEventListener()

  • document.addEventListener('DOMContentLoaded', () => {})의 의미는:
    • "document" 라는 문서 객체의 "DOMContentLoaded" 이벤트가 발생했을 때 매개변수로 지정한 콜백 함수를 실행
    • "DOMContentLoaded"는 "HTML의 문서 객체 파악 후 바로 실행"을 의미.
    • 이벤트 발생 시 실행되는 함수를 "Event Listener" / "Event Handler" 라고 한다.
<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()

  • 생성했던 이벤트 리스너 제거 시:
    • 문서 객체.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>


드디어 정리가 끝났다!

내용이 어려웠다기보단 코드 해석에 주석을 다는 작업이 길었다.

마침 노마드코더에서 들었던 강의와 맞물리는 부분이 많아서 공부 자체는 어렵지 않았었다.

이제 곧 리액트 공부가 시작된다...
아직 자바스크립트도 아주 기초만 아는데 내가 할 수 있을까?

못하면 어쩔려나 그냥 해야하는데!

걱정은 미리 하지말고 그냥 공부나 열심히 하자... 오늘도 내 몸엔 버섯이 자란다.... 🍄

출처: 혼자 공부하는 자바스크립트 (한빛미디어)

profile
공부하느라 녹는 중... 밖에 안 나가서 버섯 피는 중... 🍄

0개의 댓글