본문 바로가기

FE

1.7 문서 수정하기

모던 JavaScript 튜토리얼 파트 2. 브라우저: 문서, 이벤트, 인터페이스를 읽고 정리, 기록

 

브라우저 환경과 다양한 명세서

 

브라우저 환경과 다양한 명세서

 

ko.javascript.info

 

DOM 조작: ‘생동감 있는’ 웹페이지 만드는 방법

요소 생성하기

DOM 노드를 만들 때 사용하는 메서드

  1. document.createElement(tag)

태그 이름을 사용해 새로운 요소 노드를 만든다.

let div = document.createElement('div');
  1. document.createTextNode(text)

주어진 텍스트(text)를 사용해 새로운 텍스트 노드를 만든다.

let textNode = document.createTextNode('안녕하세요.');

메시지 생성

// 1. <div> 요소 만들기
let div = document.createElement('div');

// 2. 만든 요소의 클래스를 'alert'로 설정
div.className = "alert";

// 3. 내용 채워넣기
div.innerHTML = "<strong>안녕하세요!</strong> 중요 메시지를 확인하셨습니다.";

아직 페이지에 나타나지는 않음


삽입 메서드

div가 페이지에 나타나게 하려면 document 어딘가에 div를 넣어줘야 한다.

  • node.append(노드나 문자열) - 노드나 문자열을 node 끝에 삽입
  • node.prepend(노드나 문자열) - 노드나 문자열을 node 맨 앞에 삽입
  • node.before(노드나 문자열) - 노드나 문자열을 node 이전에 삽입
  • node.after(노드나 문자열) - 노드나 문자열을 node 다음에 삽입
  • node.replaceWith(노드나 문자열) - node를 새로운 노드나 문자열로 대체

삽입 메서드에는 노드 목록이나 문자열을 넘겨줄 수 있다.

  • 문자열을 넘기면 자동으로 텍스트 노드가 만들어진다.

문자열과 요소를 한 번에 삽입하는 방법

문자열로 넘겨 텍스트 노드를 만들 땐 문자열이 “HTML”이 아닌 “문자열” 그 형태 그대로 삽입된다.

(elem.textContent 와 비슷하게 동작한다.)

<div id="div"></div>
<script>
  div.before('<p>안녕하세요</p>', document.createElement('hr'));
</script>

삽입 후 (문자열의 특수문자는 escape 처리)

&lt;p&gt;안녕하세요&lt;/p&gt;
<hr>
<div id="div"></div>

HTML 자체를 문자열로 삽입하고 싶다면

insertAdjacentHTML / Text / Element

elem.insertAdjacentHTML(where, html)

첫 번째 매개변수(where)는 elem을 기준으로 하는 상대 위치로, 다음 값 중 하나여야 한다.

  • 'beforebegin' - elem 바로 앞에 html을 삽입
  • 'afterbegin' - elem의 첫 번째 자식 요소 바로 앞에 html을 삽입
  • 'beforeend' - elem의 마지막 자식 요소 바로 다음에 html을 삽입
  • 'afterend' - elem 바로 다음에 html을 삽입
<div id="div"></div>
<script>
  div.insertAdjacentHTML('beforebegin', '<p>안녕하세요.</p>');
  div.insertAdjacentHTML('afterend', '<p>안녕히 가세요.</p>');
</script>

삽입 후 (HTML 형태로 삽입)

<p>안녕하세요.</p>
<div id="div"></div>
<p>안녕히 가세요.</p>

elem.insertAdjacentHTML(where, html)은 두 가지 형제 메서드가 있다.

  1. elem.insertAdjacentText(where, text)
    • insertAdjacentHTML과 문법은 같지만, HTML 대신 text를 ‘문자 그대로’ 삽입한다.
  2. elem.insertAdjacentElement(where, elem)
    • 같은 문법인데, 요소를 삽입한다.

노드 삭제하기

node.remove()

요소 노드를 다른 곳으로 옮길 때는 기존에 있던 노드를 지울 필요가 없다.

모든 노드 삽입 메서드는 자동으로 기존에 있던 노드를 삭제하고 새로운 곳으로 노드를 옮기기 때문이다.

<div id="first">First</div>
<div id="second">Second</div>
<script>
  // remove 메서드를 호출할 필요가 없습니다.
  second.after(first); // id가 second인 노드를 가져오고, 해당 노드의 뒤에 id가 first인 노드를 삽입
</script>

cloneNode로 노드 복제하기

기존 메시지 창과 유사항 메시지 창을 하나 더 띄워달라는 요구사항이 추가되었다면?

  • 메시지 창을 만들어주는 함수 만들기
  • 기존의 만들었던 div를 복제하고 텍스트를 수정하는 방법

복제하려는 요소가 클 때는 함수를 만드는 대신 복제를 사용하는 방법이 빠르고 간단할 수 있다.

elem.cloneNode(true)

  • elem의 ‘깊은’ 복제본이 만들어진다. 속성 전부와 자손 요소 전부가 복사된다.

elem.cloneNode(false)

  • 후손 노드 복사 없이 elem만 복제된다.
<style>
.alert {
  padding: 15px;
  border: 1px solid #d6e9c6;
  border-radius: 4px;
  color: #3c763d;
  background-color: #dff0d8;
}
</style>

<div class="alert" id="div">
  <strong>안녕하세요!</strong> 중요 메시지를 확인하셨습니다.
</div>

<script>
  let div2 = div.cloneNode(true); // 메시지 창 복제
  div2.querySelector('strong').innerHTML = '안녕히 가세요!'; // 복제한 메시지 창 내용 수정

  div.after(div2); // 복제한 메시지 창을 기존 메시지 창 다음에 보여줌
</script>

DocumentFragment

특별한 DOM 노드 타입,

여러 노드로 구성된 그룹을 감싸 다른 곳으로 전달하게 해주는 래퍼(wrapper)처럼 동작한다.

  • 문서에 있는 다른 노드를 DocumentFragment에 추가할 수 있는데, DocumentFragment를 문서 어딘가에 삽입하면 DocumentFragment는 사라지고 DocumentFragment에 추가한 노드만 남는다.
<ul id="ul"></ul>

<script>
function getListContent() {
  let fragment = new DocumentFragment();

  for(let i=1; i<=3; i++) {
    let li = document.createElement('li');
    li.append(i);
    fragment.append(li);
  }

  return fragment;
}

ul.append(getListContent()); // (*)
</script>

결과

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

DocumentFragment를 직접 사용할 일은 흔지 않다. 노드가 담긴 배열을 직접 만들어 반환할 수 있기 때문.

<ul id="ul"></ul>

<script>
function getListContent() {
  let result = [];

  for(let i=1; i<=3; i++) {
    let li = document.createElement('li');
    li.append(i);
    result.push(li);
  }

  return result;
}

ul.append(...getListContent()); // append 메서드와 ...(전개 구문)은 궁합이 잘 맞습니다.
</script>

template 요소: DocumentFragment를 기반으로하는 문법


구식 삽입,삭제 메서드 (오래된 문법)

하위 호환성을 유지하기 위해 남아있는 구식 DOM 조작 메서드도 있다.

앞서 모던한 메서드 append, prepend, before, after, remove, replaceWith를 사용하는 것이 좀 더 유연하다.

parentElem.appendChild(node)

parentElem의 마지막 자식으로 node를 추가함

parentElem.insertBefore(node, nextSibling)

node를 parentElem안의 nextSibling앞에 추가함

parentElem.replaceChild(node, oldChild)

parentElem의 자식 노드 중 oldChild를 node로 교체함

parentElem.removeChild(node)

node가 parentElem의 자식 노드라는 가정하에 parentElem에서 node를 삭제함


‘document.write’

document.write는 웹페이지에 뭔가를 더할 때 쓰는 아주 오래된 메서드이다.

<p>페이지 어딘가...</p>
<script>
  document.write('<b>자바스크립트를 사용해 Hello 입력</b>');
</script>
<p>끝</p>

document.wirte(html) 를 호출하면 html이 페에지 ‘그 자리에 즉시’ 추가된다.

html 형식의 문자열을 동적으로 만들어 사용할 수 있기 때문에 document.write(html) 는 꽤나 유연하다.

하지만 document.write는 DOM도 없고 그 어떤 표준도 없었던 과거에 만들어졌다.

근래에는 이 메서드를 찾기 힘들다..

왜냐하면 document.write 는 페이지를 불러오는 도중에만 작동하기 때문이다.

페이지가 다 로드되고 나서 document.write 를 호출하면 기존에 있던 문서 내용이 사라진다.

<p>일 초 후, 이 페이지의 내용은 전부 교체됩니다.</p>
<script>
  // 일초 후 document.write 호출
  // 페이지 로드가 끝난 후이므로 기존 내용이 사라집니다.
  setTimeout(() => document.write('<b>...사라졌습니다.</b>'), 1000);
</script>

장점도 존재한다.

브라우저는 HTML을 ‘읽는(파싱하는)’ 도중에 document.wrtie(HTML) 를 만나면 텍스트 형식의 HTML을 마치 원래 페이지에 있었던 것 마냥 해석한다.

중간에 DOM 조작을 하지 않기 때문에 속도가 매우 빨라진다. (왜 빨라지지..?)

→ DOM 구조가 완성되기 전에 페이지에 내용이 삽입되기 때문이다.

엄청나게 많은 글자를 HTML에 동적으로 추가해야 하는데 아직 페이지를 불러오는 중이고, 속도가 중요한 상황이라면 document.write가 유용할 수 있다.

하지만 실제 이런 요구 사항들이 한 번에 충족되어야 하는 상황은 흔치 않고, document.write가 눈에 띈다면 그건 그냥 오래된 스크립트라서 그럴 확률이 높다.


요약

  • 노드 생성 메서드:
    • document.createElement(tag) – 태그 이름을 사용해 새로운 요소를 만듦
    • document.createTextNode(value) – 텍스트 노드를 만듦(잘 쓰이지 않음)
    • elem.cloneNode(deep) – 요소를 복제함. deep==true일 경우 모든 자손 요소도 복제됨
  • 노드 삽입, 삭제 메서드:
    • node.append(노드나 문자열) – node 끝에 노드를 삽입
    • node.prepend(노드나 문자열) – node 맨 앞에 노드를 삽입
    • node.before(노드나 문자열) –- node 이전에 노드를 삽입
    • node.after(노드나 문자열) –- node 다음에 노드를 삽입
    • node.replaceWith(노드나 문자열) –- node를 대체
    • node.remove() –- node를 제거
    문자열을 삽입, 삭제할 땐 문자열을 ‘그대로’ 넣으면 된다.
  • ‘구식’ 메서드:
    • parent.appendChild(node)
    • parent.insertBefore(node, nextSibling)
    • parent.removeChild(node)
    • parent.replaceChild(newElem, node)
    이 메서드들은 전부 node를 반환합니다.
  • html에 HTML을 넣으면 메서드 elem.insertAdjacentHTML(where, html)은 where 값에 따라 특정 위치에 HTML을 삽입함
    • "beforebegin" – elem 바로 앞에 html을 삽입
    • "afterbegin" – elem의 첫 번째 자식 요소 바로 앞에 html을 삽입
    • "beforeend" – elem의 마지막 자식 요소 바로 다음에 html을 삽입
    • "afterend" – elem 바로 다음에 html을 삽입
    문자열이나 요소 삽입에 쓰이는 유사 메서드 elem.insertAdjacentText와 elem.insertAdjacentElement도 있는데, 잘 쓰이지는 않음
  • 페이지 로딩이 끝나기 전에 HTML을 삽입해주는 메서드:
    • document.write(html)

'FE' 카테고리의 다른 글

1.9 요소 사이즈와 스크롤  (0) 2024.11.17
1.8 스타일과 클래스  (0) 2024.11.16
1.6 속성과 프로퍼티  (0) 2024.11.14
1.5 주요 노드 프로퍼티 (2)  (1) 2024.11.13
1.5 주요 노드 프로퍼티 (1)  (0) 2024.11.12