7. DOM (Document Object Model)

김관주·2023년 10월 11일
0

웹시스템

목록 보기
7/22

DOM (Document Object Model)

Document Object Model

  • A convention for describing the structure of an HTML document and a programming interface for interacting with the browser.
  • HTML 문서의 구조를 설명하기 위한 규약 및 브라우저와 상호 작용하기 위한 프로그래밍 인터페이스.
  • An Interface to access HTML document Data from programs so that we can change the document structure, style and content.
  • 프로그램에서 HTML 문서 데이터에 접근하여 문서 구조, 스타일 및 내용을 변경할 수 있는 인터페이스입니다.
    • DOM is a fully object-oriented representation of the web page, and it can be modified with a scripting language such as JavaScript
  • DOM 객체: HTML 문서의 각 element들이 브라우저에 loading 되면서 객체화 된 것
    • DOM 객체를 통해 change the document structure, style and content.

DOM Tree and Use of DOM

  • DOM is a tree, and a tree consists of nodes
    • Root node is the document, and its single child is the html
  • Node in the DOM tree is an instance of the Node class
    • It has parentNode and childNode properties (as well as nodeName and nodeType)

DOM and JavaScript

  • The DOM is not a programming language, but without it, the JavaScript language wouldn't have any model or notion of the web pages, XML pages and elements with which it is usually concerned (e.g. jQuery, ReactJS, VueJS, NodeJS).
  • Every element in a document is part of the document object model for that document, so they can all be accessed and manipulated using the DOM and a scripting language like JavaScript
let section = document.getElementsById(‘section’);
section.style.color = “red”
  • Other language choices: Python, Java, Ruby, PHP, Dart, etc

DOM “Get” Methods

  • The DOM provides “get” methods that allow you to quickly locate specific HTML elements.

  • document.getElementById: can retrieve an element by its ID

document.getElementById('content'); // <div id="content">...</div>
  • document.getElementsByClassName: returns a collection of elements that have the given class name
const callouts = document.getElementsByClassName('callout');

DOM “Query” Methods

  • The DOM provides “query” methods that allow you to locate HTML elements by the element’s relationship to other elements.

  • querySelector and querySelectorAll allow you to use CSS selectors.

    • CSS selectors allow you to identify elements by their name (<p>, <div>, etc.), their ID, their class (or combination of classes), or any combination thereof.

    • To identify elements by name, simply use the name of the element (without angle brackets). > ,<

      • ‘a’ will match all <a> tags in the DOM, and ‘br’ will match all the <br> tags.
    • To identify elements by their class, use a period(마침표 .) before the class name: .callout will match all elements that have the class callout.

const el = document.querySelector("p");
const el = document.querySelector(".callout");
  • Return a result as a NodeList, allowing you to iterate through all of them

  • class 선택자 (class selector)

document.querySelector(".myClass")
  • id 선택자 (id selector)
document.querySelector("#myid");
  • 속성 선택자 (attribute selector)
document.querySelector('[href]');

코드에는 요소가 여러 개 있는 경우, querySelector() 메소드의 깊이 우선 순차 검색 방식에 의해 코드의 가장 윗 줄에 있는 요소를 리턴한다.

querySelectorAll() 메소드는 DOM에 있는 모든 요소의 목록(NodeList 형태)을 리턴합니다.

Manipulating DOM Elements

  • Each element has two properties, textContent and innerHTML, that allow you to access (and change) the element’s content.
    • textContent access text data only
    • innerHTML access with tags HTML (which results in new DOM nodes)
const para1 = document.getElementsByTagName('p')[0];
para1.textContent; // "This is a simple HTML file."
para1.innerHTML; // "This is a <i>simple</i> HTML file."
para1.textContent = "Modified HTML file";
para1.innerHTML = "<i>Modified</i> HTML file"; 
  • However (warning), assigning to textContent and innerHTML is a destructive operation: it will replace whatever is in that element, no matter how big or complex.
    • For example, you could replace the entire page contents by setting innerHTML on the <body> element!

cf) 위의 코드를 보면 document.getElementsByTagName[0]이라는 인덱싱을 사용하는 것을 보아 여러개의 태그를 한번에 반환한다는 것을 알 수 있다.

Creating New DOM Elements

  • document.createElement creates a new element, but it doesn’t add it to the DOM
const p1 = document.createElement('p');
const p2 = document.createElement('p');
p1.textContent = "I was created dynamically!";
p2.textContent = "I was also created dynamically!";
  • Use insertBefore and appendChild to add them to DOM
const parent = document.getElementById('content');
const firstChild = parent.childNodes[0];
parent.insertBefore(p1, firstChild);
parent.appendChild(p2);

innerHTML 값이 여러번 바뀌고, 바뀔 때마다 DOM Tree가 교체된다면 좋은 방법이라고 보기 힘들 것이다.
요소 변경이 아닌 요소 삽입만을 해야 하는 상황이라면 insertAdjacentHTML을 사용하라

  • insertAdjacentHTML: to insert HTML content as a string at a specified position relative to the element.
    • 2nd argument specifies the position (beforebegin, afterbegin, beforeend, etc.)
element.insertAdjacentHTML(position, text);

const foodArray = ["김밥", "방어", "사과", "오렌지"]
const FOOD_TEMPLATE = (food) => '<div class="list_food">'+food+'</div>'
foodArray.forEach(food => body.insertAdjacentHTML("beforeend", FOOD_TEMPLATE(food)))

요소 아래의 돔 트리를 싹 갈아엎는 innerHTML과 달리 돔 fragment를 삽입하기만 하는 insertAdjacentHTML 메소드를 사용하면 이미 추가된 요소들을 다시 파싱하고 돔 트리에 넣지 않아도 된다는 큰 이점을 보여준다.

Styling Elements

- We can do. However, it is generally considered good practice to use CSS classes instead of modifying the individual properties of an element (with JS)

  • Ex) if we wanted to highlight all paragraphs that contain the word ‘unique’

css

.highlight {
    background: #ff0;
    font-style: italic;
}

myapp.js

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');
    }
}

highlightParas('unique');

containing이 문자열인지 확인하고, 문자열이라면 정규 표현식 객체로 변환합니다. 정규 표현식은 단어 경계(\b)를 사용하여 주어진 문자열을 단어 단위로 검색하며, i 플래그는 대소문자를 무시하도록 합니다.
해당 문자열을 포함하고 있다면 'highlight' 클래스를 추가하여 강조 효과를 적용합니다.

  • 단어 경계의 의미 -> every unique와에서 띄어쓰기 되어있으면 그런 unique도 포함한다는 이야기.
  • !containing.test(p.textContent)는 p.textContent에 containing 정규 표현식과 일치하지 않는 경우에 true를 반환하고, 일치하는 경우에 false를 반환합니다.

만약 class 속성 말고 다른 속성(id나 name)을 추가하고 싶다면?
css 파일에서 바꾸는것은 물론이고 스크립트에서는 다음과 같이 수정한다.

const p = document.querySelector('p'); // 요소를 가져옴
p.setAttribute('id', 'my-paragraph'); // ID 속성을 추가

0개의 댓글