JavaScript for Web

1. ParentNode.children, 그리고 element.childNodes

이 두 가지 속성은 모두, 부모로 지정한 요소에 속한 자식 노드를 담은 유사 배열을 가져온다. 그러나 ParentNode.children는 HTML tag로 둘러싸인 엘리먼트만을, element.childNodes는 그 외의 모든 요소(tab키, 스페이스 키 입력으로 인한 공백을 나타내는 text등)까지 함께 가져온다.

ParentNode.children

[ ParentNode.children | MDN ]
ParentNode의 속성 children은 호출된 요소의 모든 자식 노드의 elements를 담고있는 실시간 HTMLCollection을 반환한다. 각 자식 요소를 컬렉션 안에서 접근하기 위해서 item() 메소드를 이용하거나 Javascript 배열 스타일의 문법을 사용할 수 있다.

const body = document.querySelector('body');

console.log(body.children);
// HTMLCollection(6) 
// [header, div#background-bar, form#tweet-form, main#main, footer, script, background-bar: div#background-bar, tweet-form: form#tweet-form, main: main#main]

HTMLCollection

[ HTMLCollection | MDN ]
HTMLCollection 인터페이스는 요소의 문서 내 순서대로 정렬된 일반 컬렉션(arguments처럼 배열과 유사한 객체)을 나타내며 리스트에서 선택할 때 필요한 메서드와 속성을 제공한다. HTML DOM 내의 HTMLCollection은 문서가 바뀔 때 실시간으로 업데이트된다.

element.childNodes

[ element.childNodes | MDN ]
childNodes는 주어진 요소의 NodeList형 자식 노드 모음(collection)을 반환한다. childNodes 속성은 읽기 전용이다.

const body = document.querySelector('body');

console.log(body.childNodes);
// NodeList(13) 
// [text, header, text, div#background-bar, text, form#tweet-form, text, main#main, text, footer, text, script, text]

NodeList

[ NodeList | MDN ]
NodeList객체는 일반적으로 element.childNodes와 같은 속성과 document.querySelectorAll와 같은 메서드에 의해 반환되는 노드의 컬렉션이다.
NodeList 는 유사배열이지만 forEach()를 사용하여 반복할 수 있다. 또한 Array.from()을 사용하여 배열로 변환 할 수도 있다.

더 알아보기 : HTML Tag와 HTML Element

[ What Is An HTML Tag Versus an HTML Element? | Jennifer Kyrnin ]

2. template Element

[ <template>: 컨텐츠 템플릿 엘리먼트 | MDN ]
HTML 컨텐츠 템플릿 <template> 엘리먼트는 페이지에 로드될 때 렌더링되지 않지만, JavaScript를 사용하는 동안 후속적으로 인스턴트화되는 클라이언트 사이드 컨텐츠를 유지하기 위한 메커니즘이다. 이는 Document에서 나중에 사용하기 위해 저장하는 컨텐츠 조각으로 생각하면 된다. 페이지가 로딩되는 동안 파서가 <template> 엘리먼트의 컨텐츠를 처리하지만, 컨텐츠가 유효한지만 확인한다. 엘리먼트의 컨텐츠는 렌더링되지 않는다.

template 엘리먼트 사용하기

id값이 'main'인 div 노드의 자식으로 template 엘리먼트를 삽입하려고 한다.
우선 아래처럼 HTML을 작성한다.

<!-- template 엘리먼트 -->
<template id="template">
  <div id="box-wrapper"></div>
</template>


<div id="main-wrapper">
  <div id="main">
<!-- template 엘리먼트의 컨텐츠를 삽입하려는 부분 -->
  </div>
</div>

다음으로 자바스크립트를 작성한다. 우선 자식 노드를 삽입할 부모 노드를 getElementById() 혹은 querySelector() 메서드를 이용해 가져온다.

const parent = document.getElementById('main');

같은 방법으로 template 엘리먼트를 가져온다.

// const parent = document.getElementById('main');

const temp = document.getElementById('template');

template 엘리먼트의 요소(content)를 복사한다. HTMLTemplateElement.content 속성과 Node.cloneNode() 메서드를 이용했다.

// const parent = document.getElementById('main');

// const temp = document.getElementById('template');
const clone = temp.content.cloneNode(true);

마지막으로 복사한 요소들을 부모 노드에 삽입한다. appendChild() 메서드를 이용했다.

const parent = document.getElementById('main');

const temp = document.getElementById('template');
const clone = temp.content.cloneNode(true);

parent.appendChild(clone);

HTMLTemplateElement.content

[ HTMLTemplateElement.content | MDN ]
HTMLTemplateElement.content 속성은 template 엘리먼트의 콘텐츠를 반환한다.

Node.cloneNode()

[ Node.cloneNode() | MDN ]
Node.cloneNode() 메서드는 이 메서드를 호출한 Node 의 복제된 Node를 반환한다. 해당 node의 children까지 복제하려면 true, 해당 node 만 복제하려면 false를 입력한다.

const myTemplate = document.getElementById('template');

const clone = myTemplate.content.cloneNode(true);

Document.importNode()

[ Document.importNode() | MDN ]
현재 문서가 아닌 외부 문서의 노드를 복사하여 현재 문서에 넣을 수 있도록 해준다.

const myTemplate = document.getElementById('template');

const clone = document.importNode(myTemplate.content, true);

3. HTMLElement.dataset

[ HTMLElement.dataset | MDN ]
[ 데이터 속성 사용하기 | MDN ]
data-* 속성은 표준이 아닌 속성이나 추가적인 DOM 속성, Node.setUserData()과 같은 다른 조작을 하지 않고도, 의미론적 표준 HTML 요소에 추가 정보를 저장할 수 있다.

dataset 속성 사용하기

HTML 엘리먼트의 속성에 원하는 데이터를 입력할 수 있다. 속성명은 'data-'로 시작하여 원하는 이름을 지정한다(이름을 정하는 룰 자세히 보기).

<div 
  id="dumpling"
  data-color='하얀색' 
  data-name='만두' 
  data-age='9'>
</div>

dataset에 저장된 데이터를 불러오기 위해서 우선 대상 엘리먼트를 가져온다.

const dumpling = document.getElementById('dumpling');

아래와 같은 형식으로 dataset에 저장된 데이터를 얻을 수 있다.

const color = dumpling.dataset.color;
const name = dumpling.dataset.name;
const age = dumpling.dataset.age;

얻은 데이터를 이용해 엘리먼트에 텍스트를 추가해 보면..

dumpling.textContent = `${color} 고양이 ${name}${age}살입니다.`

// 하얀색 고양이 만두는 9살입니다.