[JS/브라우저] DOM

play·2022년 5월 18일
0

Chapter1. DOM 기초

1-1 DOM
1-2 HTML에 JavaScript 적용

Chapter2. DOM 다루기

Chapter3. 이벤트 객체


Chapter1. DOM 기초

학습목표


📌 DOM(Document Object Model)

HTML 요소를 Object(JavaScript Object)처럼 조작(Manipulation)할 수 있는 Model.
즉, JavaScript를 사용할 수 있으면, DOM으로 HTML을 조작할 수 있다. DOM을 이용하면 HTML로 구성된 웹 페이지를 동적으로 움직이게 만들 수 있다.

HTML 문서의 계층적 구조와 정보를 표현
프로퍼티와 메서드를 제공하는 트리 자료 구조(자료구조의 형태: 객체 형태. Object)

HTML과 DOM의 구조

📌 HTML에 JavaScript 적용하기

<script> 태그

HTML에 JavaScript를 적용하기 위해서 사용하는 태그
<script>요소는 등장과 함께 실행된다

  • 문서의 어느 곳이든 스크립트 배치에 제한을 두지 않음
  • HTML은 파싱 도중, script 태그를 만나게 되면 중간에 파싱이 멈춘다.
  • 자바스크립트의 삽입 위치에 따라 스크립트 실행순서, 브라우저 렌더링에 영향을 미친다.

1. <head> 안쪽에 삽입하는 경우

<head>
  <script>
  // 코드내용
  </script>
</head>
  • 브라우저 렌더링에 방해가 되어 무거운 스크립트가 실행되는 경우 오랫동안 완성되지 못한 화면을 노출하게 된다.
  • 문서를 초기화하거나 설정하는 가벼운 스크립트들이 자주 사용된다.
  • 문서의 DOM구조가 필요한 스크립트의 경우 document.onload같은 로드 이벤트가 추가되어야 에러없이 작동된다.
  • script파일이 크고 무겁다면, HTML 파싱을 하다 만 화면을 사용자들에게 보여주고 말 것.

2. <body> 요소가 끝나기 전에 삽입하는 경우

...
  <script>
  ...
  </script>
</body>
  • 브라우저 렌더링이 완료된 상태에서 스크립트가 실행되기에 콘텐츠를 변경하는 스크립트의 경우 화면에 노출된 상태로 변화된다

  • 대부분의 스크립트의 위치로 추천되는 위치

  • 문서의 DOM구조가 완료된 시점에서 실행되므로 다른 추가설정이 필요없다

  • HTML을 다운받고 파싱을 마친 후 script 태그를 읽기 때문에 1번의 방법보다 콘텐츠를 빠르게 볼 수 있다.

  • 단점: 웹이 자바스크립트에 의존적이라면 HTML이 파싱돼도 의미가 없을 것

3. async

<head>
    <script async src="script.js"></script>
</head>
  • async는 HTML파일을 파싱하다 script 태그를 만나면 HTML를 마저 파싱하는 동시에 script를 다운로드 시킨다.
    그리고 실행시키는데 실행시키는 동안에는 HTML파싱이 멈추게 된다.

  • 장점은 자바스크립트에 의존적인 웹을 좀 더 빨리 실행시킬 수 있다는 점.

  • 단점은 결국에는 HTML파싱이 자바스크립트 파일을 실행시키는 동안에 멈추게 돼 그냥 head부분에 넣는 1번의 상황에서 일어날 문제를 겪을 수 있다.

  • 또한, 실행시켜야 할 script 태그가 여러개일 때, 순서에 상관 없이 먼저 다운로드 받아지는 script를 먼저 실행시키기 때문에 해당 프로젝트가 script 파일의 실행 순서에 영향을 받는다면 문제가 될 수 있다.

4. defer

<head>
    <script defer src="script.js"></script>
</head>
  • 가장 이상적인 방법.
  • defer은 HTML을 파싱하다 script 태그를 만나면 async와 마찬가지로 HTML을 파싱하면서 script는 동시에 다운로드만 시켜둔다.
  • 차이점은 HTML 파싱이 완료된 후에 script를 실행
  • HTML파싱이 중간에 멈출 염려도 없고, 2번의 단점도 개선시킬 수 있다.
  • 여러개의 script 태그를 이용해도 미리 다운을 다 받고 HTML도 끝까지 파싱시킨 후에 순서대로 실행되기 때문에 async의 단점을 보완

DOM 구조

트리구조

회사의 조직도와 유사.
body가 가장 상위에 있고, 아래에 여러 구성요소가 부모-자식 관계를 가짐

  • 부모가 자식을 여러 개 가지고, 부모가 하나인 구조가 반복. 즉, 부모가 가진 하나 또는 여러 개의 자식 엘리먼트를 조회하는 코드를 작성한다면, 여러 번 반복해서 실행하는 코드가 필요

Chapter2. DOM 다루기

1. CREATE

const tweetDiv = document.createElement('div')
// [코드] 새롭게 생성한 div element를 변수에 할당합니다.
// tweetDiv 라는 요소는 현재 공중부양 중이라 화면에 나타나지 않음

2. APPEND

공중에 떠있는 엘리먼트를 확인하기 위해서는 APPEND 해야함.

tweetDiv 를 트리 구조에 연결

document.body.append(tweetDiv)
// [코드] 변수 tweetDiv에 담긴 새로운 <div> 요소를 <body> 요소에 append 합니다.

3. READ

원시 자료형인 변수의 값을 조회 : 변수의 이름으로 직접 조회
참조 자료형 : 배열은 index를, 객체는 key를 이용해 값을 조회
DOM : DOM으로 HTML 엘리먼트의 정보를 조회하기 위해서는 querySelector의 첫 번째 인자로 셀렉터(selector)를 전달하여 확인. 셀렉터로는 HTML 요소("div"), id("#tweetList"), class(.tweet) 세 가지가 가장 많이 사용됨

1) querySelector();

querySelector 에 '.tweet' 을 첫 번째 인자로 넣으면, 클래스 이름이 tweet 인 HTML 엘리먼트 중 첫 번째 엘리먼트를 조회

const oneTweet = document.querySelector('.tweet')
[코드] querySelector로 클래스 이름이 tweet인 HTML 요소를 조회합니다.

querySelectorAll();

여러 개의 요소를 한 번에 가져옴

이렇게 조회한 HTML 요소들은 배열처럼 for문을 사용할 수 있다.

+) getElementBy : querySelector 와 비슷한 역할을 하는 오래된 방식

const container = document.querySelector('#container')
const tweetDiv = document.createElement('div')
container.append(tweetDiv)
[코드] tweetDiv를 container의 마지막 자식 요소로 추가합니다.

4. UPDATE

textContent 를 사용해서, 비어있는 div 엘리먼트에 문자열을 입력

oneDiv.textContent = 'dev';
console.log(oneDiv) // <div>dev</div>

CSS 스타일링이 적용될 수 있도록, div 엘리먼트에 class를 추가

oneDiv.classList.add('tweet')
console.log(oneDiv) // <div class="tweet">dev</div>

이번에는 append를 이용해 container의 자식 요소로 추가

const container = document.querySelector('#container')
container.append(oneDiv)
[코드] append를 이용해 container의 자식 요소에 oneDiv를 추가합니다.

class와 id 말고는 다른 attribute를 추가하는 방법 : setAttribute

5. DELETE

1) 삭제하려는 위치를 알고 있는 경우
.remove()

2) 여러 개의 자식 요소를 지우려는 경우
.innerHTML

document.querySelector('#container').innerHTML = '';
[코드] id가 container인 요소 아래의 모든 요소를 지웁니다.
  • innerHTML은 보안상의 문제를 갖고 있음.
  • removeChild : 자식 요소를 지정해서 삭제하는 메서드.
    모든 자식 요소를 삭제하기 위해, 반복문(while, for, etc.)을 활용할 수 있다.

자식 요소가 남아있지 않을 때까지, 첫 번째 자식 요소를 삭제하는 코드

const container = document.querySelector('#container');
while (container.firstChild) {
  container.removeChild(container.firstChild);
}
/* removeChild 와 while 을 이용해 자식 요소를 삭제하면, 
제목에 해당하는 H2 "Tweet List"까지 삭제된다.
*/

이를 방지하기 위한 방법 1.

const container = document.querySelector('#container');
while (container.children.length > 1) {
 container.removeChild(container.lastChild);
}
[코드] container의 자식 요소가 1개만 남을 때까지, 마지막 자식 요소를 제거합니다.
  1. const tweets = document.querySelectorAll('.tweet')
    tweets.forEach(function(tweet){
       tweet.remove();
    })
    // or
    for (let tweet of tweets){
       tweet.remove()
    }
    [코드] 클래스 이름이 tweet인 요소만 찾아서 제거합니다.

Chapter3. 이벤트 객체

사용자 입력(onclick, onkeyup, onscroll 등)을 트리거로 발생한 이벤트 정보를 담은 객체

사용자가 버튼을 클릭하면, 그 버튼의 textContent(또는 innerHTML)을 이용해 메뉴의 이름을 가져옴.
사용자가 누른 버튼에 따라 출력되는 이름이 달라지므로, 클릭된 이벤트 객체에서 메뉴의 이름을 가져옴

이벤트 발생 시 작동하는 함수를 할당하는 방법

  1. DOM 객체에 onclick을 직접 지정
function displayAlert() {
  alert('코드스테이츠에 오신 것을 환영합니다')
}
document.querySelector('#apply').onclick = displayAlert
  1. addEventListener라는 메서드를 사용해서 할당
document.querySelector('#apply').addEventListener('click', function(){
   alert("코드스테이츠에 오신 것을 환영합니다")
})

document.createElement('div') : <div>요소를 생성

document.querySelector 조회

document.cloneNode 복제

document.importNode template 을 활용하여 내용을 붙여 넣을 때 사용

--
<div> 요소를 전부 조회하는 방법

  1. document.getElementsByTagName('div')
  2. document.querySelectorAll('div')

document.querySelector('div') 최상단 <div>요소 하나만 조회

document.getElementById('div') id가 <div>요소 하나를 조회

document.getElementsByClassName('div') class가 <div>요소 여러 개를 조회

id가 world인 <div>요소의 내용을 "Earth"로 바꾸기

  1. document.querySelector('#world').textContent = "Earth"
  2. document.querySelector('#world').innerHTML = "Earth"
profile
블로그 이사했습니다 🧳

0개의 댓글