본문 바로가기
JavaScript

JavaScript] document 수정

by Fastlane 2022. 11. 11.
728x90
반응형

출처 : https://javascript.info/modifying-document

 

DOM변경의 key는 live page를 생성이다. 어떻게 새로운 element를 생성하고 존재하는 page content를 수정하는지 알아보자. 

Example: show a message

<style>
.alert {
  padding: 15px;
  border: 1px solid #d6e9c6;
  border-radius: 4px;
  color: #3c763d;
  background-color: #dff0d8;
}
</style>

<div class="alert">
  <strong>Hi there!</strong> You've read an important message.
</div>

JavaScript로 동일한 div를 만들어보자. 

Creating an element

DOM nodes를 만드는 데 2가지 함수가 있다. 

let div = document.createElement('div');
// 주어진 tag로 새로운 element node를 생성한다.
let textNode = document.createTextNode('Here I am');
//주어진 text로 새로운 text node를 생성한다.

대부분의 경우 우리는 element node를 생성한다. 

Creating the message

message div를 만드는 데 3steps이 있다. 

// 1. Create <div> element
let div = document.createElement('div');

// 2. Set its class to "alert"
div.className = "alert";

// 3. Fill it with the content
div.innerHTML = "<strong>Hi there!</strong> You've read an important message.";

이제 element를 만들었다. 하지만 div라는 변수에만 있고, page에는 없다. 

Insertion methods

div가 보여지기 위해서, document안의 어딘가에 추가를 해야한다. 

document.body.append(div)

<style>
.alert {
  padding: 15px;
  border: 1px solid #d6e9c6;
  border-radius: 4px;
  color: #3c763d;
  background-color: #dff0d8;
}
</style>

<script>
  let div = document.createElement('div');
  div.className = "alert";
  div.innerHTML = "<strong>Hi there!</strong> You've read an important message.";

  document.body.append(div);
</script>

insertion methods

  • node.append(...nodes or strings) - node 끝에 추가한다. 
  • node.prepend(...nodes or strings) - node 앞에 추가한다. 
  • node.before(...nodes or strings) - node 전에 추가한다. 
  • node.after(...nodes or strings) - node 위에 추가한다. 
  • node.replaceWith(...nodes or strings) - node를 교체한다. 
<ol id="ol">
  <li>0</li>
  <li>1</li>
  <li>2</li>
</ol>

<script>
  ol.before('before'); // insert string "before" before <ol>
  ol.after('after'); // insert string "after" after <ol>

  let liFirst = document.createElement('li');
  liFirst.innerHTML = 'prepend';
  ol.prepend(liFirst); // insert liFirst at the beginning of <ol>

  let liLast = document.createElement('li');
  liLast.innerHTML = 'append';
  ol.append(liLast); // insert liLast at the end of <ol>
</script>

output :

before

  1. prepend
  2. 0
  3. 1
  4. 2
  5. append

after

최종 html은 이렇게 된다. 

before
<ol id="ol">
  <li>prepend</li>
  <li>0</li>
  <li>1</li>
  <li>2</li>
  <li>append</li>
</ol>
after

text는 HTML이 아닌 text로 추가되며, <, >와 같은 문자는 escaping된다. 

elem.textContent처럼 문자열을 안전하게 추가할 수 있다. 

<div id="div"></div>
<script>
  div.before('<p>Hello</p>', document.createElement('hr'));
</script>

output : 
&lt;p&gt;Hello&lt;/p&gt;
<hr>
<div id="div"></div>

만약에, elem.innerHTML처럼 HTML string을 html로 추가하고 싶은 경우에는 어떻게 할까?

insertAdjacentHTML/Text/Element

elem.insertAdjacentHTML(where, html)함수가 꽤 유용하다. 

첫번째 parameter는 다음 중 하나가 된다. 

  • beforebegin
  • afterbegin
  • beforeend
  • afterend

두번째 parameter는 HTML string이며, HTML로 추가된다. 

<div id="div"></div>
<script>
  div.insertAdjacentHTML('beforebegin', '<p>Hello</p>');
  div.insertAdjacentHTML('afterend', '<p>Bye</p>');
</script>

OUTPUT : 
<p>Hello</p>
<div id="div"></div>
<p>Bye</p>

유사한 함수가 2가지 더 있다. 하지만 주로 append/prepend/before/after를 사용한다. 

  • elem.insertAdjacentText(where, text) 
  • elem.insertAdjacentElement(where, text)

Node 삭제

node를 삭제하기 위해서 node.remove()함수를 사용한다. 

<style>
.alert {
  padding: 15px;
  border: 1px solid #d6e9c6;
  border-radius: 4px;
  color: #3c763d;
  background-color: #dff0d8;
}
</style>

<script>
  let div = document.createElement('div');
  div.className = "alert";
  div.innerHTML = "<strong>Hi there!</strong> You've read an important message.";

  document.body.append(div);
  setTimeout(() => div.remove(), 1000);
</script>

element위치를 옮기고 싶다면 삭제할 필요가 없다. 

모든 insertion method는 자동적으로 old place에서 node를 삭제시킨다. 

<div id="first">First</div>
<div id="second">Second</div>
<script>
  // no need to call remove
  second.after(first); // take #second and after it insert #first
</script>

Cloning nodes: cloneNode

어떻게 하나 이상의 유사한 메시지를 추가할 수 있을까?

함수를 만들 수 있지만, 기존 div를 clone하고, 내부 text를 수정하는 방법도 있다. 

 

big element를 복사해야 한다면, 후자가 더 빠르고 간단하다. 

elem.cloneNode(true) : deep clone, 모든 attributes와 subelements 포함

elem.cloneNode(false) : child elements 제외

 

<style>
.alert {
  padding: 15px;
  border: 1px solid #d6e9c6;
  border-radius: 4px;
  color: #3c763d;
  background-color: #dff0d8;
}
</style>

<div class="alert" id="div">
  <strong>Hi there!</strong> You've read an important message.
</div>

<script>
  let div2 = div.cloneNode(true); // clone the message
  div2.querySelector('strong').innerHTML = 'Bye there!'; // change the clone

  div.after(div2); // show the clone after the existing div
</script>

DocumentFragment

DocumentFragment는 node lists를 감싸는 wrapper와 같은 DOM node이다. 

다른 node를 append할 수 있고, 어딘가 insert를 할때 content가 insert된다. 

<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>

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

DocumentFragment는 드물게 사용된다. DocumentFragment 대신에, node arrray를 반환할 수 있다. 

<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 + "..." operator = friends!
</script>

Old-school insert/remove methods

  • parentElem.appendChild(node)
  • parentElem.insertBefore(node, nextSibling)
  • parentElem.replaceChild(node, oldChild)
  • parentElem.removeChild(node)

과거 script를 이해하기위한 정보이지, 해당 함수를 개발 시 사용하지는 않는다. 

 

A word about “document.write”

web-page에 뭔가 추가하기 위한 원시적인 함수가 있다. 

document.write

<p>Somewhere in the page...</p>
<script>
  document.write('<b>Hello from JS</b>');
</script>
<p>The end</p>

document.write(html)은 html을 page에 그 자리에 바로 추가한다. 오래된 함수로 아직 동작하지만, 기능이 제한적이다. document.write 함수는 오직 page 로딩 시에만 동작한다. 로딩 이후에 호출하면 기존재하는 document content는 삭제된다. 

<p>After one second the contents of this page will be replaced...</p>
<script>
  // document.write after 1 second
  // that's after the page loaded, so it erases the existing content
  setTimeout(() => document.write('<b>...By this.</b>'), 1000);
</script>

따라서, 로딩된 이후 단계에서는 사용불가하다. 하지만, document.write함수는 빠르다.  많은양의 HTML을 dynamically하게 추가하기 위해서는 유용하다. 

Summary

  • Methods to create new nodes:
    • document.createElement(tag) – creates an element with the given tag,
    • document.createTextNode(value) – creates a text node (rarely used),
    • elem.cloneNode(deep) – clones the element, if deep==true then with all descendants.
  • Insertion and removal:
    • node.append(...nodes or strings) – insert into node, at the end,
    • node.prepend(...nodes or strings) – insert into node, at the beginning,
    • node.before(...nodes or strings) –- insert right before node,
    • node.after(...nodes or strings) –- insert right after node,
    • node.replaceWith(...nodes or strings) –- replace node.
    • node.remove() –- remove the node.
    Text strings are inserted “as text”.
  • There are also “old school” methods:
    • parent.appendChild(node)
    • parent.insertBefore(node, nextSibling)
    • parent.removeChild(node)
    • parent.replaceChild(newElem, node)
    All these methods return node.
  • Given some HTML in html, elem.insertAdjacentHTML(where, html) inserts it depending on the value of where:
    • "beforebegin" – insert html right before elem,
    • "afterbegin" – insert html into elem, at the beginning,
    • "beforeend" – insert html into elem, at the end,
    • "afterend" – insert html right after elem.
    Also there are similar methods, elem.insertAdjacentText and elem.insertAdjacentElement, that insert text strings and elements, but they are rarely used.
  • To append HTML to the page before it has finished loading:
    • document.write(html)
    After the page is loaded such a call erases the document. Mostly seen in old scripts.
728x90
반응형

댓글