🧙‍♂️

[JS] DOM 조작하기


DOM을 조작해 요소를 새롭게 만들고 페이지에 있는 기존 콘텐츠를 어떻게 수정할 수 있는지 알아보자.

문서 수정하기

요소 생성하기

DOM 노드를 만들 때 사용하는 메서드는 두 가지다.

  • document.createElement(tag): 태그 이름을 사용해 새로운 요소 노드를 만든다.
1let div = document.createElement("div");
  • document.createTextNode(text): 주어진 텍스트를 사용해 새로운 텍스트 노드를 만든다.

새로 요소를 만들지 않고 존재하는 요소를 재활용하고 싶다면, 요소를 복제하면 된다.

  • elem.cloneNode(boolean): 불린 값이 true면 'deep copy'가 만들어진다. 속성 전부와 자손 요소 전부가 복제된다. false면 후손 노드 복사 없이 elem만 복제된다.

삽입 메서드

만든 요소를 페이지에 나타나게 하려면 document안에 넣어줘야 한다.

자바스크립트에서 지원하는 노드 삽입 메서드는 다음과 같다.

  • node.append(node or string): 노드나 문자열을 node의 마지막 항목으로 삽입한다.
  • node.prepend(node or string): 노드나 문자열을 node의 첫 항목으로 삽입한다.
  • node.after(node or string): 노드나 문자열을 node 뒤에 삽입한다.
  • node.before(node or string): 노드나 문자열을 node 앞에 삽입한다.
  • node.replaceWith(node or string): 노드나 문자열로 node를 대체한다.

삽입 메서드에 문자열을 넘겨 텍스트 노드를 만들 땐 인수로 넘긴 문자열이 'HTML'이 아닌 '문자열' 그 형태로 삽입된다. elem.textContent를 사용한 것처럼 말이다.

문자열 형태의 'HTML 그 자체'를 삽입하고 싶다면 아래 메서드를 사용할 수 있다.

  • elem.insertAdjacentHTML(where, html):
    • where: 'beforebegin', 'afterbegin', 'beforeend', 'afterend'를 넣어 elem 기준 상대 위치를 지정한다.
    • html: html 문자열을 넘겨준다.

구식 메서드

  • parent.appendChild(node)
  • parent.insertBefore(node, nextSibling)
  • parent.removeChild(node)
  • parent.replaceChild(newElem, node)

이 메서드들은 전부 node를 반환한다.

노드 삭제하기

node.remove()를 사용하면 노드를 삭제할 수 있다.

만약 존재하는 요소 노드를 다른 곳으로 옮기고 싶을 때, 기존에 있던 노드는 지울 필요가 없다. 모든 노드 삽입 메서드는 자동으로 기존에 있던 노드를 삭제하고 새로운 곳으로 노드를 옮겨주기 때문이다.

DocumentFragment

DocumentFragment는 여러 노드로 구성된 그룹을 감싸 다른 곳으로 전달해주는 택배같은 역할을 한다.

문서에 있는 다른 노드를 DocumentFragment에 추가하고, DocumentFragment를 문서 어딘가에 삽입하면 DocumentFragment는 사라지고 안의 노드만 남는다. 마치 택배를 받았을 때 내용물만 남기고 상자는 버리듯이 말이다.

1<ul id="ul"></ul>
2
3<script>
4function getListContent() {
5 let fragment = new DocumentFragment();
6
7 for(let i=1; i<=3; i++) {
8 let li = document.createElement('li');
9 li.append(i);
10 fragment.append(li);
11 }
12
13 return fragment;
14}
15
16ul.append(getListContent());
17</script>

위 코드의 최종 결과물은 아래와 같다.

1<ul>
2 <li>1</li>
3 <li>2</li>
4 <li>3</li>
5</ul>

스타일과 클래스

요소에 스타일을 적용할 수 있는 방법은 두 가지가 있다.

  • CSS에 클래스를 만들고, 요소에 클래스 추가하기
  • 프로퍼티를 style에 바로 써주기

두 방법 중 보통은 클래스를 추가하는 방법을 사용해야 한다. 유연성과 유지보수를 위해서 말이다.

클래스 조작

클래스를 위한 프로퍼티는 역사적인 배경 때문에 className이다. elem.classNameclass 속성에 대응된다.

이 프로퍼티에 뭔가 대입하면 클래스 문자열 전체가 바뀐다. 이렇게 속성값 전체를 바꾸는게 아니라 클래스 하나만 추가하거나 제거할 때elem.classList 프로퍼티를 사용해야 한다.

1<body class="main page">
2 <script>
3 // 클래스 추가
4 document.body.classList.add('article');
5
6 alert(document.body.className); // main page article
7 </script>
8</body>

classList에 구현된 메서드는 다음과 같다.

  • add/remove(): 클래스를 추가/제거
  • toggle("class"): 클래스가 존재하면 제거하고, 그렇지 않으면 추가한다.
  • contains("class"): 클래스의 존재 여부를 확인한다.

classList는 이터러블 객체이기 때문에 for..of를 사용해 클래스를 나열할 수 있다.

요소의 스타일

style 프로퍼티는 카멜 표기법을 이용해 변경한 스타일이 있는 객체로, 이 객체를 조작하면 style 속성과 대응되는 개별 프로퍼티를 조작하는 것과 같다.

  • background-color => elem.style.backgroundColor
  • z-index => elem.style.zIndex
  • border-left-width => elem.style.borderLeftWidth

style 프로퍼티에 값을 할당했다가 시간이 지나 이를 제거해야 할 때가 있다. 이때는 프로퍼티를 삭제하는 대신 빈 문자열을 할당해주어야 한다.

개별 스타일 프로퍼티를 적용하는 것은 좋지만, 이것으로 전체 스타일을 설정할 수는 없다. 문자열을 사용해 전체 스타일을 설정하고 싶다면 프로퍼티 style.cssText를 사용하면 된다.


참조: ko.javascript.info