2021-12-31 T.I.L

정종훈·2022년 3월 1일
0

T.I.L

목록 보기
2/20

DOM(Document Object Model)

DOM은 HTML 문서의 계층적 구조와 정보를 표현하며 이를 제어할 수 있는 API
즉 프로퍼티와 메서드를 제공하는 틀 자료구조이다.


노드(Node)

노드란 매듭, 절, 집합점, 중심점이라는 사전적 의미를 가지고 있으므로 여러 분야에서 넓게 이용되는 단어이다. 예를 들어 식물의 경우 줄기와 잎을 연결하는 곳을 노드라고 부르기도 한다.

HTML DOM은 노드(node)라고 불리는 계층적 단위에 정보를 저장하고 있다.

HTML DOM은 이러한 노드들을 정의하고, 그들 사이의 관계를 설명해 주는 역할을 함.

HTML에 JS 적용하기

  • HTML에 JS를 적용하기 위해서는 HTML파일에서 script 태그를 이용함.

Q1). 그럼 script태그는 어디에 위치해야 하나요?

대표적으로 head 안쪽에 삽입하거나, body태그가 끝나기 전에 삽입하거나 등이 있는데(2개 더있음)

body태그가 끝나기 전에 삽입하자!


HTML이 JavaScript에서는 어떻게 표현될까?

Example 1) HTML 예시

<html>
  <body>
    <div id="nav">
      <div class="logo"></div>
      <div class="menu-wrapper">
        <div class="menu"></div>
        <div class="menu"></div>
        <div class="menu"></div>
        <div class="profile-photo"></div>
      </div>
    </div>
    <div id="news-contents">
      <div class="news-content-wrapper">
        <div class="news-picture"></div>
        <div class="news-title"></div>
        <div class="news-description"></div>
      </div>
    </div>
    <div id="footer"></div>
  </body>
</html>

Q2)
  • body 엘리먼트의 자식 엘리먼트(element)는 총 몇 개인가요? -> 3개 (id가 nav, news-contents, footer)

console.dir(document.body);

console.dir 은 DOM을 객체의 모습으로 출력!

document.body로 body의 속성 조회가능!

  • document.body.children : 자식속성의 첫 번째 element 조회!


Q. 아니 그럼 2번째는 ? 3번째는?? 변수로 저장하자!

let newsContents = document.body.children[1];

console.dir(newsContents) // div#news-contents
  • id의 이름이 news-contents 인 div 엘리먼트의 부모 엘리먼트는 무엇인가요? -> body!
  • newsContents.ParentNodes : newsContents의 부모속성 조회!

DOM으로 HTML 조작하기

intro) document 객체에는 많은 속성과 메소드가 존재함. 모든 속성과 메소드를 외워야 할까? No.

지금 집중할 부분은 CRUD(Create, Read, Update and Delete)

  • createElement : 새로운 엘리먼트를 만드는 도구
const tweetDiv = document.createElement('div')

근데 이거 만으로는 안됨...

  • APPEND (append, appendChild)
document.body.append(tweetDiv) // body태그의 마지막으로 <div></div> 생성됨

이 메소드는 한 노드를 특정 부모 노드의 자식 노드 리스트 중 마지막 자식으로 붙인다.

-querySelector, querySelectorAll - READ

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

const oneTweet = document.querySelector('.tweet')

HTML 문서에는 클래스 이름이 tweet 인 엘리먼트가 여러 개 있는 데, 변수 oneTweet 에 할당된 엘리먼트는 단 하나!

여러 개의 엘리먼트를 한 번에 가져오기 위해서는, querySelectorAll 을 사용합니다.

이렇게 조회한 HTML 엘리먼트들은 배열처럼 for문을 사용하실 수 있다. 주의하세요! 앞서 조회한 HTML 엘리먼트들은 배열이 아닙니다! 이런 '배열 아닌 배열'을 유사 배열, 배열형 객체 등 다양한 이름으로 부릅니다. 정식 명칭은 Array-like Object 입니다.

const tweets = document.querySelectorAll('.tweet')

tweetDiv를 container의 마지막 자식 요소로 추가함.

const container = document.querySelector('#container')
const tweetDiv = document.createElement('div')
container.append(tweetDiv)


  • textContent, classList.add - UPDATE

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

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

classList.add 를 이용해 div 엘리먼트에 class를 추가합니다.

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

class 말고 다른 속성을 추가하려면

Element.setAttribute(name, value);

  • remove, removeChild - DELETE

remove 메소드를 사용해 삭제 가능

const container = document.querySelector('#container')
const tweetDiv = document.createElement('div')
container.append(tweetDiv)
tweetDiv.remove() // 이렇게 append 했던 엘리먼트를 삭제할 수 있다.

removeChild 는 자식 엘리먼트를 지정해서 삭제하는 메소드

모든 자식 엘리먼트를 삭제하기 위해, 반복문(while, for, etc.)을 활용할 수 있음

다음의 코드는 자식 엘리먼트가 남아있지 않을 때까지, 첫 번째 자식 엘리먼트를 삭제하는 코드임

const container = document.querySelector('#container');
while (container.firstChild) {
  container.removeChild(container.firstChild);
}

removeChild 와 while 을 이용해 자식 요소를 삭제하면, 제목에 해당하는 H2 "Tweet List"까지 삭제됨.

이를 방지하기 위한 방법은 여러 가지가 있습니다. 자식 요소가 담고 있는 문자열을 비교해 "Tweet List"만 남기거나, 새로운 변수를 생성하고 Tweet List를 할당해뒀다가 반복문이 끝난 뒤에 새롭게 추가할 수도 있습니다.

또는 자식 엘리먼트를 하나만 남기게 할 수도 있습니다.

const container = document.querySelector('#container');
while (container.children.length > 1) {
  container.removeChild(container.lastChild);
}

container의 자식 엘리먼트가 1개만 남을 때까지, 마지막 자식 엘리먼트를 제거합니다.

또는 직접 클래스 이름이 tweet인 엘리먼트만 찾아서 지우는 방법도 있습니다.

const tweets = document.querySelectorAll('.tweet')
tweets.forEach(function(tweet){
    tweet.remove();
})
// or
for (let tweet of tweets){
    tweet.remove()
}

위는 클래스 이름이 tweet인 엘리먼트만 찾아서 제거합니다.

Further Study
아래 키워드에 대해서 직접 검색하여 학습하세요.

  • element와 node의 차이 (difference between element and node in javascript dom)
  • children과 childNodes의 차이 (difference between children and childNodes in javascript dom)
  • removeChild와 remove의 차이 (difference between removeChild and remove in javascript dom)
  • tweets에 forEach는 되는데, reduce는 안되는 이유 (why array method is not working on nodelist)
  • tweets를 유사 배열에서 배열로 바꾸는 방법 (how to convert nodelist into javascript array)
profile
괴발개발자에서 개발자로 향해보자

0개의 댓글