[JS] DOM(Document Object Model)

Chanki Hong·2022년 12월 5일
0

JavaScript

목록 보기
18/30
post-thumbnail

  • JS는 브라우저 스크립트 언어로 시작.
  • 브라우저에서 사용할 때는 알아야 할 사항이 존재.

DOM(Document Object Model)

  • 문서 객체 모델.
  • HTML(XML) 문서(document)의 구조를 나타내는 표현(structured representation)인 동시에 프로그래밍 인터페이스. (스크립트 언어로 수정 가능)
  • 웹의 객체지향 표현. (쉽게 각 tag의 정보를 지닌 JS객체)
  • 트리 구조로 표현하고 트리는 노드(node)로 구성.
  • 루트(root) 노드를 제외하면 모든 노드에는 부모가 있음.
  • 루트 노드는 문서(document)이며, 자식 노드는 <html> 요소 하나.
  • <html> 요소의 자식 노드에는 <head><body> 가 존재.
  • DOM 트리의 모든 노드는 Node 클래스의 인스턴스.
  • Node 객체에는 트리 구조를 나타내는 parentNodechildNodes 프로퍼티가 있고,
  • 자신에 대한 프로퍼티인 nodeNamenodeType (타입을 정수로 표현)프로퍼티가 있음.
  • 다만, 모든 노드가 HTML 요소는 아님.
  • 예를 들어 <p> 태그는 HTML 요소지만, 문단에 포함된 텍스트는 텍스트 노드.
  • 노드와 요소(HTML의 요소)는 다른 개념이고 차이가 있음.
  • 아래 HTML문서를 기준으로 예시를 작성 함.
<!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>Simple HTML</title>
    <style>
      .callout {
        border: solid 1px #ff0080;
        margin: 2px 4px;
        padding: 2px 6px;
      }
      .code {
        background: #ccc;
        margin: 1px 2px;
        padding: 1px 4px;
        font-family: monospace;
      }
    </style>
    <link rel="stylesheet" href="./style.css" />
  </head>
  <body>
    <header>
      <h1>Simple HTML</h1>
    </header>
    <div id="content">
      <p>This is a <i>simple</i> HTML file.</p>
      <div class="callout">
        <p>This is as fancy as we'll get!</p>
      </div>
      <p>
        IDs (such as <span class="code">#content</span>) are unique (there can
        only be one per page).
      </p>
      <p>
        Classes (such as <span class="code">.callout</span>) can be used on may
        elements.
      </p>
      <div id="callout2" class="fancy">
        <p>A single HTML element can have multiple classes.</p>
      </div>
    </div>
    <script src="./index.js"></script>
  </body>
</html>

DOM 요소 찾기

get 메서드 이용

  • 원하는 HTML 요소를 모두 찾는 메서드.
  • HTMLCollection 의 인스턴스 반환.
  • HTMLCollection은 JS배열은 아니지만, 배열과 유사한 형태.
  • 특정 요소 1개만 존재하거나, 1번째 요소를 선택 하려면 [0](인덱스) 사용.

document.getElementById

  • ID에 해당하는 요소 반환.
console.log(document.getElementById('content')); // HTML에서 ID가 'content'인 요소를 찾아 콘솔에 출력.
// <div id="content">...</div> 출력.

document.getElementByClassName

  • 클래스(class) 이름에 해당하는 요소 반환.
console.log(document.getElementsByClassName('callout'));
// HTMLCollection[div.callout] 출력.

document.getElementByTagName

  • 태그 이름에 해당하는 요소 반환.
console.log(document.getElementsByTagName('p'));
// HTMLCollection[p, p, p, p, p] 출력.

query 메서드 이용

  • 한 가지 조건이 아니라 다른 요소와의 관계를 이용해 원하는 요소 반환. (범용적)
  • CSS 선택자를 이용. (CSS 선택자와 거의 동일)

CSS 선택자

  • 요소 선택자는 꺽쇠 없이 요소이름만 적음. div
  • 클래스 선택자는 클래스 앞에 . 을 적음. .callout
  • ID 선택자는 ID 앞에 # 을 적음. #content
  • 선택자 사이에 스페이스를 넣으면 특정 노드의 자손인 요소로 한정 가능. #content p // ID가 content인 요소의 자손인 <p>요소 선택
  • 선택자 사이에 > 기호를 넣으면 자손이 아닌 자식만 선택. #content>p // content요소의 자식인 <p>요소 선택

querySelector

  • 찾은 첫번째 요소 반환.
  • 일치하는 값이 없으면 null.
document.querySelector(".code"); // <span class="code">#content</span> 출력.

queryselectorAll

  • 찾은 모든 값을 NodeList 반환.
  • NodeList는 JS배열은 아니지만, 배열과 유사한 형태.
  • 특정 요소 1개만 존재하거나, 1번째 요소를 선택 하려면 [0](인덱스) 사용.
  • 일치하는 값이 없으면 비어있는 NodeList 반환.
document.querySelectorAll(".code");
// NodeList(2) [span.code, span.code]

HTMLCollectionNodeList

  • get 메서드에서 반환하는 HTMLCollection.
  • queryselectorAll 에서 반환하는 NodeList.
  • 이 둘은 JS배열이 아님. (유사 배열 ; [i] 인덱스 등)
  • 확산연산자를 이용하면 배열로 사용 가능.
console.log([...document.getElementsByTagName('p')]);
// [p, p, p, p, p] 출력.
  • 이 둘은 for 루프를 사용할 수 있음.

HTMLCollection

  • Live DOM Collection 객체
  • 요소(노드)의 변화 즉시 반영.
<!DOCTYPE html>
<html lang="en">
  <head>
    <style>
      .red {
        font-weight: bold;
        color: red;
      }
      .blue {
        font-weight: lighter;
        color: blue;
      }
    </style>
  </head>
  <body>
    <div class="red">빈지노</div>
    <div class="red">검정치마</div>
    <div class="red">이센스</div>
    <div class="red">스윙스</div>
    <div class="red">오웬</div>
    <script>
      const artists = document.getElementsByClassName('red');
      for (let i = 0; i < artists.length; i++) {
        artists[i].className = 'blue';
      }
    </script>
  </body>
</html>

-실행결과는 다음과 같음.

  • for문에서 빈지노 요소([0]) 의 classblue로 변하는 순간 Live DOM Collection 객체가 요소가 변한 것을 바로 반영하여, 다음 값인 검정치마([1])의 인덱스가 [0]으로 바뀜.
  • 이러한 이유로 2번째, 4번째 값이 변하지 않음.
  • Non-Live DOM Collection 객체인 NodeList 에서는 이런 현상이 발생하지 않음.
  • HTMLCollection 즉, get 메서드의 속도가 더 빠름.
  • HTMLCollectionArray. 메서드가 사용 불가. (.map(), .forEach() 등)

NodeList

  • Non-Live DOM Collection 객체
  • 요소(노드)의 변화 즉시 반영하지 않음.
  • NodeList.forEach() 는 사용 가능 하지만 .map(), .filter() 는 이용 불가.

DOM 요소 조작

  • 해당 요소에 접근하거나 수정.
  • 모든 요소에는 textContentinnerHTML 프로퍼티가 존재.

textContent

  • HTML 태그를 모두 제거하고 순수한 텍스트 데이터만 제공.
const para1 = document.getElementsByTagName('p')[0];
para1.textContent; // 'This is a simple HTML file.'
para1.textContent = 'Modified HTML file';

innerHTML

  • HTML 태그를 그대로 제공.
const para1 = document.getElementsByTagName('p')[0];
para1.innerHTML; // 'This is a <i>simple</i> HTML file.'
para1.innerHTML = 'Modified HTML file';

새로운 DOM 요소 생성

create

  • 새 노드(요소) 생성.
  • 하지만 DOM에 추가하지 않음.
const p1 = document.createElement('p'); // p태그 생성
const p2 = document.createElement('p'); // p태그 생성
p1.textContent = '새 요소 생성1';
p2.textContent = '새 요소 생성2!';

insertBerore

  • 새 요소를 특정한 위치에 추가함.
  • insertBefore(삽입할 요소, 삽입할 위치);
const p1 = document.createElement('p');
p1.textContent = '새 요소 생성1';
const parent = document.getElementById('content'); // 추가하려는 위치의 부모노드.
const firstChild = parent.childNodes[0]; // 추가하려는 첫번째 위치.
parent.insertBefore(p1, firstChild); // p1을 parent의 firstChild위치에 추가.

appendChild

  • 새 요소를 항상 마지막 위치에 추가함.
const p2 = document.createElement('p');
p2.textContent = '새 요소 생성2!';
const parent = document.getElementById('content'); // 추가하려는 위치의 부모노드.
parent.appendChild(p2); // p2를 parent의 마지막 위치에 추가.

DOM 요소 스타일링

  • 요소의 프로퍼티를 직접 수정도 가능하지만,
  • CSS 클래스를 이용하는 편이 권장.
  • 즉, 요소의 스타일을 바꾸고자 하면 그에 맞는 CSS 클래스를 새로 만들고 특정 요소에 지정.
/* 먼저 CSS에서 클래스를 만들어야 함. */
.highlight {
  background: #ff0;
  font-style: italic;
}
  • 클래스를 추가한 뒤, JS에서 unique가 들어있는 문단을 모두 하이라이트 하는 예제.
  • 모든 요소에는 클래스(HTML클래스)를 나열하는 classList 프로퍼티 존재.
  • classList 프로퍼티의 add 메서드로 클래스를 추가할 수 있음.
// 매개변수로 받은 단어가 있는 문단(p)에 하이라이트 하는 함수.
function highlightParas(containing) {
    if (typeof containing === 'string')
      containing = new RegExp(`\\b${containing}\\b`, 'i');
    const paras = document.getElementsByTagName('p');
    console.log(paras);
    for (let p of paras) {
      if (!containing.test(p.textContent)) continue;
      p.classList.add('highlight'); // 클래스를 추가할 때는 classList.add 이용.
    }
  }
  highlightParas('unique'); // unique가 있는 문단에 하이라이트.
  • 클래스를 제거할 때는 classList 프로퍼티의 remove 사용.
// highlight 클래스를 지우는 함수.
  function removeParaHighlights() {
      const paras = document.querySelectorAll('p.highlight');
      for (let p of paras) {
        p.classList.remove('highlight'); // 클래스를 제거할 때는 classList.remove 이용.
      }
    }

데이터(data-) 속성

  • HTML5에서 도입.
  • data- 로 시작하는 속성. (하이픈 뒤의 속성 이름은 모두 가능)
  • 임의의 데이터를 DOM에 저장 가능.
  • 브라우저에서는 완전히 무시함. (숨김)
<!-- 2개의 버튼에 highlightParas와 removeParaHighlights 함수를 연결 하기. -->
<!-- button 요소에 data 속성 추가. -->
<button data-action="highlight" data-containning="unique">
  Highlight paragraphs containing "unique"
  </button>
<button data-action="removeHighlights">
  Remove highlights
</button>
// 새로운 CSS선택자가 나옴. 대괄호 문법은 어떤 속성이든 찾을 수 있음. 데이터 속성은 대괄호 문법.
const highlightActions = document.querySelectorAll('[data-action="highlight"]');
highlightActions[0].dataset; // DOMStringMap {action: 'highlight', containning: 'uniqe'}; (data set 프로퍼티가 생김.)

이벤트

  • DOM API에는 약 200개의 이벤트가 정의.

click

  • 클릭 이벤트를 통해 버튼과 함수를 연결 가능.
  • 모든 요소에는 addEventListener 메서드가 존재 하고, 이벤트 발생시 호출할 함수 지정 가능.
  • 호출할 함수는 Event 타입의 객체 하나만 받음.
// button 2개를 함수와 연결.
// 새로운 CSS선택자가 나옴. 대괄호 문법은 어떤 속성이든 찾을 수 있음. 데이터 속성은 대괄호 문법.
const highlightActions = document.querySelectorAll('[data-action="highlight"]');
for (let a of highlightActions) {
  a.addEventListener('click', (evt) => {
    evt.preventDefault();
    highlightParas(a.dataset.containing); // highlightParas 함수에 data 속성의 containing요소를 삽입.
  });
}
const removeHighlightsAction = document.querySelectorAll(
  '[data-action="removeHighlights"]'
);
for (let a of removeHighlightsAction) {
  a.addEventListener('click', (evt) => {
    evt.preventDefault();
    removeParaHighlights(); // removeParaHighlights 실행.
  });
}

API(Application Programming Interface)

  • 한 프로그램(host)에서 다른 프로그램(client)으로 데이터를 주고받기 위한 방법. (코드)
    • ex) 식당 메뉴판: 식당주인(host)과 손님(client)이 음식을 주고받기 위한 방법.
  • 3가지 요소가 충족 되어야 하는데,
    • 요청 방식(method; 데이터를 줄건지, 받을건지; GET 등)
    • 자료 종류(endpoint; 어떤 데이터를 말하는지; 뉴스, 날씨 등)
    • 파라미터(자료요청에 필요한 추가정보; 아이디, 회차 등)
  • 공개 여부에 따라서,
    • public API: 누구나 사용 가능.
    • private API: 조직 등에서 사용 가능.
    • partner API: 권한이 있는 사용자만 가능.
  • Web API, Windows API 등 모든 프로그램은 API를 가짐.
  • API마다 정해진 요청(request)응답(response)이 존재하고,
  • 이 형식이 작성된 문서를 API가이드.

WEB API


0개의 댓글