분류 javascript

8 장. JavaScript로 HTML 요소 조작

컨텐츠 정보

  • 조회 376 (작성일 )

본문

문서 객체 모델(DOM) 


JavaScript는 그렇게 나쁘지 않습니다. 브라우저에서 실행되는 스크립팅 언어로서 웹 페이지를 조작하는 데 정말 유용합니다. 이 장에서는 HTML 문서와 해당 요소를 상호 작용하고 수정하는 데 어떤 기능이 있는지 살펴 보겠습니다. 먼저 문서 객체 모델을 이해해 봅시다.


https://github.com/valentinogagliardi/Little-JavaScript-Book/blob/v1.0.0/manuscript/chapter8.md 


문서 객체 모델은 브라우저 내부에서 수행하는 모든 작업의 ​​기본 개념입니다. 그러나 정확히 무엇입니까? 웹 페이지를 방문하면 브라우저는 모든 HTML 요소를 해석하는 방법을 알아냅니다. 따라서 메모리에 저장된 HTML 문서의 가상 표현을 만듭니다. HTML 페이지는 트리와 같은 구조로 변환되고 모든 HTML 요소는 리프(leaf)가 되어 부모 분기에 연결됩니다. 이 간단한 HTML 페이지를 고려하십시오.


<!DOCTYPE html>
<html lang="ko">
<head>
    <title>간단한 홈페이지!</title>
</head>
<body>
<h1>간단한 홈페이지!</h1>
</body>
</html>


브라우저가 위의 HTML을 스캔하면 HTML 구조의 미러인 문서 객체 모델이 생성됩니다. 이 구조의 맨 위에는 루트 요소라고 하는 문서(document)가 있으며 여기에는 다른 요소인 html이 들어 있습니다. html 요소에는 제목이 포함된 head가 포함됩니다. 그런 다음 h1을 포함하는 본문이 있습니다. 모든 HTML 요소는 특정 유형 (인터페이스라고도 함)으로 표시되며 텍스트 또는 다른 중첩 요소를 포함 할 수 있습니다.


document (HTMLDocument)
  |
  | --> html (HTMLHtmlElement)
          |  
          | --> head (HtmlHeadElement)
          |       |
          |       | --> title (HtmlTitleElement)
          |                | --> text: "간단한 홈페이지!"
          |
          | --> body (HtmlBodyElement)
          |       |
          |       | --> h1 (HTMLHeadingElement)
          |              | --> text: "간단한 홈페이지!"

모든 HTML 요소는 Element의 자손이지만 대부분은 더 전문화 됩니다. 요소가 속하는 "종"을 찾기 위해 프로토타입을 검사 할 수 있습니다. 예를 들어 h1 요소는 HTMLHeadingElement입니다.


document.querySelector('h1').__proto__

// Output: HTMLHeadingElement


HTMLHeadingElement는 HTMLElement의 "후손(descendant)"입니다.


document.querySelector('h1').__proto__.__proto__

// Output: HTMLElement


이 시점에서 (특히 초보자의 경우) 문서(document)와 창(window) 사이에 약간의 혼동이 있을 수 있습니다. 글쎄, 윈도우는 브라우저를 참조하고 반면에 문서는 현재 HTML 페이지입니다. window는 브라우저에서 실행되는 모든 JavaScript 코드에서 직접 액세스 할 수 있는 전역 객체입니다. JavaScript "기본(native)"객체가 아니라 브라우저 자체에 의해 노출됩니다. window에는 많은 속성과 메서드가 있습니다. 여기 몇 가지가 있습니다.


window.alert('Hello world'); // Shows an alert
window.setTimeout(callback, 3000); // Delays execution
window.fetch(someUrl); // makes XHR requests
window.open(); // Opens a new tab
window.location; // Browser location
window.history; // Browser history
window.navigator; // The actual device
window.document; // The current page


다음과 같은 속성이 전역적이므로 창(window)을 생략 할 수도 있습니다.


alert('Hello world'); // Shows an alert
setTimeout(callback, 3000); // Delays execution
fetch(someUrl); // makes XHR requests
open(); // Opens a new tab
location; // Browser location
history; // Browser history
navigator; // The actual device
document; // The current page


setTimeout() (3 장) 또는 window.navigator와 같은 일부 메소드에 이미 익숙해야 합니다. 사용자의 언어를 알아 내고 싶을 때 유용합니다.


if (window.navigator) {
  var lang = window.navigator.language;
  if (lang === "ko-KR") {
    // show something
  }

  if (lang === "en-US") {
    // show something else
  }
}


window에는 훨씬 더 많은 메소드(method)가 있으며 모든 메소드를 다루는 것은 불가능합니다. 자세한 내용은 MDN 문서를 확인하십시오. 다음 섹션에서는 DOM에 대해 자세히 살펴 보겠습니다.


노드, 요소 및 DOM 조작 


문서(document) 인터페이스에는 현재 HTML 페이지 내에서 HTML 요소를 선택하는 메소드인 querySelector()와 같은 여러 유틸리티가 있습니다.


document.querySelector('h1');


window는 현재 창의 브라우저를 나타내며 다음 지침은 위와 동일합니다.


window.document.querySelector('h1');


어쨌든 다음 구문이 더 일반적이며 다음 섹션에서 많이 사용할 것입니다.


document.methodName();


HTML 요소를 선택하기 위한 querySelector() 이외에도 훨씬 유용한 메소드가 있습니다.


// returns a single element
document.getElementById('testimonials'); 

// returns an HTMLCollection
document.getElementsByTagName('p'); 

// returns a NodeList
document.querySelectorAll('p');


HTML 요소를 선택할 수 있을 뿐만 아니라 내부 상태를 상호 작용하고 수정할 수도 있습니다. 예를 들어 주어진 요소의 내부 내용을 읽거나 변경할 수 있습니다.


// Read or write
document.querySelector('h1').innerHtml; // Read
document.querySelector('h1').innerHtml = ''; // Write! Ouch!


DOM의 모든 HTML 요소는 "노드(Node)"이기도 합니다. 실제로 노드 유형을 다음과 같이 검사 할 수 있습니다.


document.querySelector('h1').nodeType;


이 예는 Element 유형의 노드에 대한 식별자인 1을 반환합니다. 노드 이름을 검사 할 수도 있습니다.


document.querySelector('h1').nodeName;

"H1"


여기서 노드 이름은 대문자로 반환 됩니다. 일반적으로 DOM에서 4 가지 유형의 노드를 처리합니다.

  • 문서(document) : 루트 노드 (nodeType 9)
  • Element 유형의 노드 : 실제 HTML 태그 (nodeType 1)
  • 속성 유형의 노드 : 모든 HTML 요소의 속성 (속성)
  • Text 유형의 노드 : 요소의 실제 텍스트 내용 (nodeType 3)

요소는 노드(Node)이고 노드는 속성(properties) (속성(attributes)이라고도 함)을 가질 수 있으므로 JavaScript 개발자는 해당 속성을 검사하고 조작 할 수 있습니다.


// Returns true or false
document.querySelector('a').hasAttribute('href');

// Returns the attribute text content, or null
document.querySelector('a').getAttribute('href');

// Sets the given attribute
document.querySelector('a').setAttribute('href', 'someLink');


앞서 DOM은 트리와 같은 구조라고 했습니다. 이 특성은 HTML 요소에도 반영됩니다. 모든 요소에는 부모와 자식이 있을 수 있으며 요소의 특정 속성을 검사하여 볼 수 있습니다.


// Returns an HTMLCollection
document.chidren;

// Returns a NodeList
document.chidNodes;

// Returns a Node
document.querySelector('a').parentNode;

// Returns an HTML element
document.querySelector('a').parentElement;


HTML 요소를 선택하고 쿼리하는 방법을 보았습니다. 어때요? Element 유형의 새 노드를 생성하기 위해 기본 DOM API는 다음과 같이 createElement 메소드를 제공합니다.


var heading = document.createElement('h1');


그리고 텍스트를 생성하기 위해 createTextNode를 사용합니다 :


var text = document.createTextNode('Hello world');


새 HTML 요소 안에 텍스트를 추가하여 두 노드를 함께 결합 할 수 있습니다. 마지막으로 제목 요소를 루트 문서에 추가 할 수도 있습니다.


var heading = document.createElement('h1');
var text = document.createTextNode('Hello world');
heading.appendChild(text);
document.body.appendChild(heading);


remove() 메소드를 사용하여 문서 오브젝트 모델에서 노드를 제거 할 수도 있습니다. 요소에서 메소드를 호출하면 페이지에서 노드가 사라집니다.


document.querySelector('h1').remove();


브라우저에서 JavaScript로 작업을 시작하기 위해 알아야 할 전부입니다. 괴상한 원에서는 이러한 명령어를 DOM 조작이라고 합니다. 다음 섹션에서는 DOM을 잘 사용하지만 먼저 "DOM 이벤트(events)"에 대해 이야기 해야 하므로 빠른 우회를 할 것입니다.


DOM and events 


DOM 요소는 똑똑합니다. 텍스트 및 기타 HTML 요소를 포함 할 수 있을 뿐만 아니라 "방출(emit)"하고 "이벤트(event)"에도 반응합니다. 웹 사이트로 이동하여 브라우저 콘솔을 엽니다. 다음을 사용하여 요소를 선택하십시오.


document.querySelector('p')


이 속성을 확인하십시오.


document.querySelector('p').onclick


어떤 유형의 개체입니까?


typeof document.querySelector('p').onclick // "object"


"object"! 그리고 왜 지구상에서 "onclick"이라고 불리는가? 약간의 직감으로 우리는 그것이 요소에 대한 마법의 속성이며 클릭에 반응 할 수 있다고 상상할 수 있습니까? 바로 그거죠. 궁금한 경우 HTML 요소의 프로토 타입 체인을 탐색 할 수 있습니다. 모든 요소는 또한 요소이며 차례로 노드이며 EventTarget이기도 합니다. 간단한 점검으로 확인할 수 있습니다.


document.querySelector('p') instanceof EventTarget // true


모든 HTML 요소의 아버지인 EventTarget을 호출하고 싶지만 JavaScript에는 실제 상속이 없습니다 (5 장 참조). HTML 요소가 연결된 다른 객체의 속성을 볼 수 있는 것과 비슷합니다. 따라서 모든 HTML 요소는 EventTarget과 동일한 특성 인 이벤트를 생성하는 기능을 공유합니다. 그러나 실제로 이벤트란 무엇입니까? 예를 들어 HTML 버튼을 사용하십시오. 당신이 그것을 클릭하면 이벤트입니다. 작은 .onclick 객체를 사용하면 요소를 클릭하자마자 실행되는 JavaScript 함수를 등록 할 수 있습니다. 이벤트에 전달 된 함수를 "이벤트 리스너(event listener)"또는 "이벤트 핸들러(event handler)"라고 합니다.


Events and listeners 


DOM에 이벤트 리스너를 등록하는 세 가지 방법이 있습니다. 첫 번째 형식은 구식이며 논리와 마크업을 혼합하므로 피해야 합니다.


<!-- BAD -->
<button onclick="console.log('clicked')">CLICK ME</button>


두 번째 옵션은 이벤트의 이름을 딴 객체에 의존합니다. 예를 들어 .onclick 객체에 함수를 등록하여 click 이벤트를 들을 수 있습니다.


document.querySelector("button").onclick = handleClick;

function handleClick() {
  console.log("Clicked!");
}


이 구문은 더 깨끗하며 인라인 핸들러의 좋은 대안입니다. addEventListener를 기반으로 한 세 번째의 최신 양식도 있습니다.


document.querySelector("button").addEventListener("click", handleClick);

function handleClick() {
  console.log("Clicked!");
}


개인적으로 나는 이 양식을 더 좋아하지만 .on으로 최대 브라우저 호환성을 유지하려고 노력합니다. 이제 HTML 요소와 이벤트 리스너가 생겼으므로 DOM 이벤트를 조금 더 살펴 보겠습니다.


이벤트 객체, 이벤트 기본값 및 이벤트 버블링 


이벤트 핸들러로 전달 된 모든 함수는 기본적으로 "event"라는 오브젝트를 수신합니다.


var button = document.querySelector("button");
button.addEventListener("click", handleClick);

function handleClick() {
  console.log(event);
}


함수 본문에서 바로 사용할 수 있지만 내 코드에서는 명시적으로 매개 변수로 선언하는 것을 선호합니다.


function handleClick(event) {
  console.log(event);
}


이벤트 객체는 "필수 사항"입니다. 이벤트 메소드를 호출하여 이벤트의 동작을 제어 할 수 있기 때문입니다. 실제로 이벤트에는 특히 "기본"및 "버블링"과 같은 특정 특성이 있습니다. HTML 링크를 고려하십시오. 다음 마크업으로 click-event.html이라는 새 HTML 파일을 작성하십시오.


<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <title>Click event</title>
</head>
<body>
<div>
    <a href="/404.html">click me!</a>
</div>
</body>
<script src="click-event.js"></script>
</html>


브라우저에서 파일을 실행하고 링크를 클릭하십시오. 링크의 클릭 이벤트에 대한 기본 동작은 href 속성에 지정된 실제 페이지로 이동하는 것입니다. 그러나 기본 설정을 차단할 수 있는 방법이 있다면 어떻게 해야 합니까? 이벤트 오브젝트에서 사용 가능한 메소드 preventDefault()를 입력하십시오. 다음 코드를 사용하여 click-event.js라는 새 파일을 만듭니다.


var button = document.querySelector("a");
button.addEventListener("click", handleClick);

function handleClick(event) {
  event.preventDefault();
}


브라우저에서 페이지를 새로 고치고 지금 링크를 클릭하십시오. 페이지에서 벗어날 수는 없습니다. 방금 "event default"을 발견했습니다! 기본 동작이 적용되는 유일한 HTML 요소는 링크가 아닙니다. 양식의 기능은 동일합니다. 11 장에서는 기본 동작을 살펴볼 수 있습니다. HTML 요소가 다른 요소 안에 중첩 될 때 나타나는 또 다른 흥미로운 특성이 있습니다. 다음 HTML을 고려하십시오.


<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <title>Nested events</title>
</head>
<body>
<div id="outer">
    I am the outer div
    <div id="inner">
        I am the inner div
    </div>
</div>
</body>
<script src="nested-events.js"></script>
</html>


그리고 다음 JavaScript 코드 :


// nested-events.js

var outer = document.getElementById('inner');
var inner = document.getElementById('outer');

function handleClick(event){
    console.log(event);
}

inner.addEventListener('click', handleClick);
outer.addEventListener('click', handleClick);


외부 div 용과 내부 div 용의 두 가지 이벤트 리스너가 있습니다. 콘솔을 연 상태에서 브라우저에서 HTML 페이지를 사용해 보는 것이 좋습니다. 내부 div를 정확하게 클릭하십시오. 당신은 무엇을 봅니까?


Event bubbling 


두 가지 이벤트가 인쇄되었습니다! 그것은 실제로 일어나는 사건입니다. 브라우저 작동 방식의 버그처럼 보이고 이벤트 객체에서 다시 호출되는 stopPropagation()으로 버블링을 비활성화하는 방법이 있습니다.


//
function handleClick(event) {
  event.stopPropagation();
  console.log(event);
}
///


구현이 좋지 않은 것처럼 보이지만 너무 많은 이벤트 리스너를 등록하는 것이 실제로 성능에 좋지 않은 상황에서 버블링이 발생합니다. 다음 예를 고려하십시오.


<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <title>Event bubbling</title>
</head>
<body>
<ul>
    <li>one</li>
    <li>two</li>
    <li>three</li>
    <li>four</li>
    <li>five</li>
</ul>
</body>
<script src="event-bubbling.js"></script>
</html>


이 목록에 몇 개의 이벤트 리스너를 등록 하시겠습니까? 답은 하나입니다. li에 대한 모든 클릭을 가로 채기 위해 ul에 등록된 리스너는 하나뿐입니다.


// event-bubbling.js

var ul = document.getElementsByTagName("ul")[0];

function handleClick(event) {
  console.log(event);
}

ul.addEventListener("click", handleClick);


보시다시피 이벤트 버블링은 성능을 향상 시키는 실용적인 방법입니다. 실제로 이벤트 리스너를 등록하면 브라우저에서 비용이 많이 드는 작업이며 방대한 요소 목록의 경우 성능 저하가 발생할 수 있습니다. 더 많이 알면 ...


JavaScript를 사용하여 HTML 테이블 생성 


HTML은 정적 마크업 언어입니다. 일부 HTML 요소를 정의한 후에는 CSS를 사용하여 HTML 요소를 수정하는 방법이 없습니다. JavaScript는 우리의 친구가 될 것이며 JavaScript 기술을 새롭게 하기 위해 간단한 연습을 할 것입니다. "왜 jQuery가 아닌 순수한 JavaScript를 사용해야 합니까?" jQuery가 사라지고 있다는 점에 유의하십시오. 부트스트랩 5는 의존성에서 그것을 제거하고 더 많은 것들이 그것을 떨어뜨립니다. 이것 뒤에는 타당한 이유가 있습니다. 네이티브 DOM API는 완전하고 성숙하여 jQuery를 쓸모 없게 만듭니다.


이제 코딩을 시작하겠습니다. 객체 배열이 주어지면 HTML 테이블을 동적으로 생성하려고 합니다. HTML 테이블은 <table> 요소로 표시됩니다. 모든 테이블에는 <thead> 요소로 정의 된 헤더도 있을 수 있습니다. 헤더에는 하나 이상의 행 <tr>이 있을 수 있으며 모든 헤더 행에는 <th> 요소로 표시되는 셀이 있습니다. 이렇게 :


<table>
    <thead>
    <tr>
        <th>name</th>
        <th>height</th>
        <th>place</th>
    </tr>
    </thead>
    <!-- more stuff here! -->
</table>


그러나 더 있습니다. 모든 테이블에는 대부분 본문이 있으며 <tbody>에 의해 정의되며 <tbody>는 여러 행 <tr>을 포함합니다. 모든 행에는 실제 데이터가 포함 된 셀이 있을 수 있습니다. 테이블 셀은 <td>로 정의됩니다. 전체 테이블은 다음과 같습니다.


<table>
    <thead>
    <tr>
        <th>name</th>
        <th>height</th>
        <th>place</th>
    </tr>
    </thead>
    <tbody>
    <tr>
        <td>Monte Falco</td>
        <td>1658</td>
        <td>Parco Foreste Casentinesi</td>
    </tr>
    <tr>
        <td>Monte Falterona</td>
        <td>1654</td>
        <td>Parco Foreste Casentinesi</td>
    </tr>
    </tbody>
</table>


우리의 임무는 이제 JavaScript 객체 배열에서 시작하여 테이블을 생성하는 것입니다. build-table.html이라는 새 파일을 만들고 선택한 폴더에 저장하십시오.


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Build a table</title>
</head>
<body>
<table>
<!-- here goes our data! -->
</table>
</body>
<script src="build-table.js"></script>
</html>


동일한 폴더에 build-table.js라는 다른 파일을 만들고 다음 배열로 코드를 시작하십시오 (작성하는 모든 새 JavaScript 파일의 맨 위에 "use strict"가 표시되어야 함).


"use strict";

var mountains = [
  { name: "Monte Falco", height: 1658, place: "Parco Foreste Casentinesi" },
  { name: "Monte Falterona", height: 1654, place: "Parco Foreste Casentinesi" },
  { name: "Poggio Scali", height: 1520, place: "Parco Foreste Casentinesi" },
  { name: "Pratomagno", height: 1592, place: "Parco Foreste Casentinesi" },
  { name: "Monte Amiata", height: 1738, place: "Siena" }
];


이제 테이블에 대해 생각해 봅시다. 우선 먼저 <thead>가 필요합니다. createElement를 사용하고 싶을 수도 있습니다.


document.createElement('thead')


잘못된 것은 아니지만 테이블에 대한 MDN 설명서를 자세히 보면 흥미로운 세부 정보가 표시됩니다. <table>은 몇 가지 흥미로운 메소드를 포함하는 인터페이스인 HTMLTableElement입니다. 가장 유용한 것 중 하나는 HTMLTableElement.createTHead()이며 <thead>를 만드는 데 도움이 됩니다.


먼저 generateTableHead라는 첫 번째 JavaScript 함수로 시작하겠습니다.


function generateTableHead(table) {
  var thead = table.createTHead();
}


우리 함수는 선택자를 가져와 주어진 테이블에 <thead>를 만듭니다.


function generateTableHead(table) {
  var thead = table.createTHead();
}

var table = document.querySelector("table");

generateTableHead(table);


브라우저에서 build-table.html을 여십시오 : 아무것도 없습니다! 그러나 브라우저 콘솔을 열면 테이블에 새로운 <thead>가 첨부 된 것을 볼 수 있습니다. 헤더를 채울 시간입니다! 먼저 그 안에 행을 만들어야 합니다. HTMLTableElement.insertRow()와 같은 다른 방법이 있습니다. 이 정보를 통해 기능을 확장 할 수 있습니다.


function generateTableHead(table) {
  var thead = table.createTHead();
  var row = thead.insertRow();
}


이 시점에서 행을 생성 할 수 있습니다. 소스 배열을 보면 이름, 높이, 장소 등의 객체에 원하는 정보가 있음을 알 수 있습니다.


var mountains = [
  { name: "Monte Falco", height: 1658, place: "Parco Foreste Casentinesi" },
  { name: "Monte Falterona", height: 1654, place: "Parco Foreste Casentinesi" },
  { name: "Poggio Scali", height: 1520, place: "Parco Foreste Casentinesi" },
  { name: "Pratomagno", height: 1592, place: "Parco Foreste Casentinesi" },
  { name: "Monte Amiata", height: 1738, place: "Siena" }
];


이것은 우리가 함수에 다른 매개 변수를 전달할 수 있음을 의미합니다. 헤더 셀을 생성하기 위해 반복하는 배열 :


function generateTableHead(table, data) {
  var thead = table.createTHead();
  var row = thead.insertRow();
  for (var i = 0; i < data.length; i++) {
    var th = document.createElement("th");
    var text = document.createTextNode(data[i]);
    th.appendChild(text);
    row.appendChild(th);
  }
}


불행히도 헤더 셀을 만드는 기본 방법이 없으므로 document.createElement( "th")를 사용합니다. 또한 텍스트 노드를 작성하기 위한 document.createTextNode(data [i]) 및 모든 태그에 새 요소를 추가하기 위한 appendChild()에 주목할 가치가 있습니다. 이런 방식으로 요소를 만들고 조작 할 때 "제국적인"DOM 조작에 대해 이야기합니다. 현대의 프론트 엔드 라이브러리는 "선언적"접근 방식을 선호하여 이 문제를 해결하고 있습니다. 브라우저에 단계별로 명령하는 대신 필요한 HTML 요소를 선언하고 라이브러리가 나머지를 처리합니다.


코드로 돌아가서 첫 번째 함수를 다음과 같이 사용할 수 있습니다.


var table = document.querySelector("table");
var data = Object.keys(mountains[0]);
generateTableHead(table, data);


이제 실제 테이블 데이터 생성으로 넘어갈 수 있습니다. 다음 함수는 generateTableHead와 비슷한 논리를 구현하지만 이번에는 두 개의 중첩 된 for 루프가 필요합니다. 가장 안쪽 루프에서 우리는 일련의 td를 생성하기 위한 또 다른 기본 방법을 이용할 것입니다. 메소드는 HTMLTableRowElement.insertCell()입니다. 앞서 만든 동일한 파일에 generateTable이라는 다른 함수를 추가하십시오.


function generateTable(table, data) {
  for (var i = 0; i < data.length; i++) {
    var row = table.insertRow();
    for (var key in data[i]) {
      var cell = row.insertCell();
      var text = document.createTextNode(data[i][key]);
      cell.appendChild(text);
    }
  }
}


위 함수는 HTML 테이블과 객체 배열을 인수로 전달하는 것입니다.


generateTable(table, mountains);


generateTable의 논리를 조금 살펴 보자. 매개 변수 데이터는 mountains에 해당하는 배열입니다. 가장 바깥 쪽 for 루프는 배열을 순환하며 모든 요소에 대해 행을 만듭니다.


function generateTable(table, data) {
  for (var i = 0; i < data.length; i++) {
    var row = table.insertRow();
    // omitted for brevity
  }
}


가장 안쪽의 루프는 주어진 객체의 모든 키를 순환하며 모든 객체에 대해 키 값을 포함하는 텍스트 노드를 만듭니다.


function generateTable(table, data) {
  for (var i = 0; i < data.length; i++) {
    var row = table.insertRow();
    for (var key in data[i]) {
      // inner loop
      var cell = row.insertCell();
      var text = document.createTextNode(data[i][key]);
      cell.appendChild(text);
    }
  }
}


모든 단계를 수행 한 경우 다음 코드로 끝나야 합니다.


var mountains = [
  { name: "Monte Falco", height: 1658, place: "Parco Foreste Casentinesi" },
  { name: "Monte Falterona", height: 1654, place: "Parco Foreste Casentinesi" },
  { name: "Poggio Scali", height: 1520, place: "Parco Foreste Casentinesi" },
  { name: "Pratomagno", height: 1592, place: "Parco Foreste Casentinesi" },
  { name: "Monte Amiata", height: 1738, place: "Siena" }
];

function generateTableHead(table, data) {
  var thead = table.createTHead();
  var row = thead.insertRow();
  for (var i = 0; i < data.length; i++) {
    var th = document.createElement("th");
    var text = document.createTextNode(data[i]);
    th.appendChild(text);
    row.appendChild(th);
  }
}

function generateTable(table, data) {
  for (var i = 0; i < data.length; i++) {
    var row = table.insertRow();
    for (var key in data[i]) {
      var cell = row.insertCell();
      var text = document.createTextNode(data[i][key]);
      cell.appendChild(text);
    }
  }
}


다음과 같이 호출했습니다.


var table = document.querySelector("table");
var data = Object.keys(mountains[0]);
generateTable(table, mountains);
generateTableHead(table, data);


우리의 테이블을 생산할 것입니다!


The resulting HTML table 


무슨 생각하는지 압니다. 지금까지 작성한 코드를 향상 시킬 수 있습니다. 다음 장에서는 JavaScript 모듈을 리팩토링하겠습니다.


결론 


문서 객체 모델은 웹 브라우저가 메모리에 보관하는 웹 페이지의 가상 사본입니다. DOM 조작은 DOM에서 HTML 요소를 작성, 수정 및 제거하는 작업입니다. 과거에는 더 간단한 작업에도 jQuery를 사용했지만, 현재는 원시 API가 성숙하여 jQuery를 더 이상 사용하지 않습니다.

반면에 jQuery는 곧 사라지지 않지만 모든 JavaScript 개발자는 기본 API로 DOM을 조작하는 방법을 알아야 합니다. 그렇게 하는 데는 여러 가지 이유가 있습니다. 추가 라이브러리는 JavaScript 응용 프로그램의 로드 시간과 크기를 증가시킵니다. 기술 인터뷰에서 DOM 조작이 많이 나온다는 것은 말할 것도 없습니다. DOM에서 사용 가능한 모든 HTML 요소에는 특정 개수의 속성과 메서드를 노출하는 인터페이스가 있습니다.


MDN의 우수한 문서를 머리 위로 사용하는 방법에 대해 의문이 있는 경우 DOM을 조작하는 가장 일반적인 방법은 새 HTML 요소를 작성하기 위한 document.createElement(), DOM 내에 텍스트 노드를 작성하기 위한 document.createTextNode()입니다.

마지막으로 새 HTML 요소 또는 텍스트 노드를 기존 요소에 추가하기 위한 .appendChild()가 있습니다. HTML 요소에는 DOM 이벤트라고도 하는 이벤트를 생성하는 기능도 있습니다. 가장 주목할 만한 이벤트는 "click", "submit", "drag", "drop"등입니다.

DOM 이벤트에는 "default" 및 버블링과 같은 고유한 동작이 있습니다. JavaScript 개발자는 이러한 속성을 활용할 수 있으며, 특히 이벤트 버블링의 경우 DOM에서 이벤트 처리 속도를 높이는 데 유용합니다.

현대의 프론트 엔드 라이브러리는 오늘날 네이티브 API에 대해 잘 알고 있는 것이 좋지만 의심 할 여지가 없는 이점을 제공합니다. "vanilla"JavaScript를 사용하여 큰 JavaScript 응용 프로그램을 구축 할 수 있지만 Angular, React 및 Vue가 많은 도움을 줄 수 있습니다.