본문 바로가기

Web/Javascript

[JAVASCRIPT] DOM - 노드 조작

텍스트 조작

API 설명
nodeValue 노드의 텍스트 값을 변경한다. 텍스트 노드를 선택해야만 텍스트를 변경할 수 있다.
textContent  요소노드의 텍스트 노드를 변경한다. HTML 마크업을 파싱하지 않는다.
innerText textContent 와 마찬가지로 텍스트 노드를 변경한다.
textContent 보다 느리고 CSS 에 영향을 받는다. 사용하지 않는 것이 좋다.

nodeValue

<body>
    <div id="app">Hello</div>
    <script>
        const $app = document.querySelector("#app");
        // nodeValue
        console.log($app.nodeValue); // null
        console.log($app.firstChild.nodeValue); // Hello
        // chage text
        $app.firstChild.nodeValue = "world";
        console.log($app.firstChild.nodeValue) // world
    </script>
</body>

textContent

<body>
    <div id="app">
        Hello
        <span>World</span>
    </div>
    <script>
        const $app = document.querySelector("#app");
        // nodeValue
        console.log($app.textContent); // Hello World 

        // chage text
        $app.textContent = "Good";
        console.log($app.textContent) // Good;

        $app.textContent = '<div> Good </div>';
        console.log($app.textContent) // <div> Good </div>;
    </script>
</body>

내부에 요소 노드가 존재하여도 text 형태 노드만 반환한다. 

내부에 텍스트를 삽입하면 모든 자식 노드가 제거되고 할당된 텍스트가 추가된다.

HTML 마크업 형태를 파싱하지 않는다.

DOM 조작

새로운 돔 노드가 추가, 생성, 삭제시 리플로우 리페인트가 발생하여 성능에 영향을 끼친다.

최적화에 신경 써야 한다.

API 설명
innerHTML 콘텐츠 영역 내에 값을 취득, 변경한다. HTML 마크업을 문자열로 변환한다.
insertAdjacentHTML 기존 요소를 제거하지않고 위치를 지정해 요소를 삽입한다.

innerHTML

<body>
    <div id="app">
        Hello
        <span>World</span>
    </div>
    <script>
        const $app = document.querySelector("#app");
        
        console.log($app.innerHTML); //  Hello \n <span>World</span>
        $app.innerHTML = `<span> new World </span>`; 
        console.log($app.innerHTML); // <span> new World </span>
    </script>
</body>

조회시 내부 text 와 요소노드 모두 포함하여 있는 그대로 돌려준다.

HTML 텍스트 삽입시 파싱되어 내부에 직접 적용된다. 

<body>
    <ul id="app">
        <li>apple</li>
    </ul>
    <script>
        const list = ["banana", "orange"];
        const $app = document.querySelector("#app");
        
        for(let i = 0 ; i < list.length ; i++){
            $app.innerHTML += `<li>${list[i]}</li>`;
        }
    </script>
</body>

배열을 통해 여러 노드를 생성한다. 

innerHTML 은 조작이 간단하고 직관적이나 크로스 사이트 스크립팅 공격에 취약하다.

insertAdjacentHTML

기존 요소를 제거하지 않고 새로운 요소를 지정된 위치에 삽입한다. 

첫 번째 인자로 InsertPosition, 두번째 인자로 문자열을 넣는다. 

첫 번째 인자의 종류로는 "beforebegin", "afterbegin", "beforeend", "afterend" 이다.

각각의 삽입 위치는 아래와 같다.

    <!-- beforebegin -->
    <div id="app">
        <!-- afterbegin -->
        <span>Hello</span>
        <!-- beforeend -->
    </div>
    <!-- afterend -->
<body>
    <div id="app">
        <p>Hello</p>
    </div>
    <script>
        const $app = document.querySelector("#app");
        
        $app.insertAdjacentHTML('beforebegin', "<p> beforebegin </p>");
        $app.insertAdjacentHTML('afterbegin', "<p> afterbegin </p>");
        $app.insertAdjacentHTML('beforeend', "<p> beforeend </p>");
        $app.insertAdjacentHTML('afterend', "<p> afterend </p>");
    </script>
</body>

innerHTML 과 마찬가지로 마크업 문자열을 파싱하고 크로스 사이트 스크립팅 공격에 취약하다. 

노드 생성

API 설명
createElement 요소 노드를 생성한다.
createTextNode 텍스트 노드를 생성한다.
createDocumentFragment 부모노드 대신 사용한다. 기존 DOM 에 추가하기 위한 용도로 사용
<body>
    <div id="app"></div>
    <script>
        const $app = document.querySelector("#app");
        
        const $p = document.createElement("span");
        const textNode = document.createTextNode("Hello");
        $p.append(textNode);
        $app.append($p);
    </script>
</body>

createElement 로 생성한 요소노드는 생성됐을뿐 DOM 트리에 달려 있지 않다. 

따라서 DOM 트리에 추가해야 한다.

TextNode 도 마찬가지로 생성된후 별도의 DOM 트리 추가 작업이 필요하다.

// 텍스트 노드 생성후 자식 노드로 추가
$li.appendChild(document.createTextNode("apple"));
// 직접 추가
$li.textContent = "apple";

여러 노드 생성

<body>
    <ul id="app"></ul>
    <script>
        const $app = document.querySelector("#app");
        const list = ["apple", "banana", "orange"];

        list.forEach((v, i) => {
            const $li = document.createElement("li"); // li 노드 생성
            const textNode = document.createTextNode(v); // 텍스트 노드 생성
            $li.appendChild(textNode);  // li 노드에 text 노드 삽입
            $app.appendChild($li); // 완성된 li 노드를 $app 노드에 삽입
        });
        
    </script>
</body>

계속해서 DOM 요소에 추가하는 것은 비용이 큰 작업이다. 따라서 아래와 같이 해결할 수 있다. 

createDocumentFragment

<body>
    <ul id="app"></ul>
    <script>
        const $app = document.querySelector("#app");

        const list = ["apple", "banana", "orange"];
        const $fragment = document.createDocumentFragment();
        list.forEach((v, i) => {
            const $li = document.createElement("li"); // li 노드 생성
            const textNode = document.createTextNode(v); // 텍스트 노드 생성
            $li.appendChild(textNode);  // li 노드에 text 노드 삽입
            $fragment.appendChild($li); // 완성된 li 노드를 $fragment 에 삽입
        });
        $app.appendChild($fragment);
    </script>
</body>

노드 삽입

API 설명
append 인자로 전달받은 노드를 마지막 자식노드로 추가한다. 
appendChild 인자로 전달받은 노드를 마지막 자식노드로 추가한다.
단 노드 형태가 아니면 랜더링 되지 않는다.
insertBefore 첫번째 인수로 전달받은 노드를 두번째 인수로 전달받은 노드 앞에 삽입한다.

append 

<body>
    <ul id="app"></ul>
    <script>
        const $app = document.querySelector("#app");

        const $span = document.createElement("span");
        $span.textContent = "Hi";

        $app.append("Hello");
        $app.append($span);
        $app.append("<p>Good</p>");
    </script>
</body>

전달받은 인자를 마지막에 추가한다. HTML 형태로 마크업 하지 않으며 text 형태를 직접 사용가능하다.

appendChild

<body>
    <ul id="app"></ul>
    <script>
        const $app = document.querySelector("#app");

        const $span = document.createElement("span");
        $span.textContent = "Hi";
        const $text = document.createTextNode("Hello");

        $app.appendChild("Hello"); // Error, parameter 1 is not of type 'Node'.
        $app.appendChild($span);
        $app.appendChild($text);
        $app.appendChild("<p>Good</p>"); // Error, parameter 1 is not of type 'Node'.
    </script>
</body>

Node 형태만 삽입이 가능하다. text도 text node 로 생성후 삽입해야한다. 

insertBefore

<body>
    <ul id="app">
        <li>a</li>
        <li>b</li>
    </ul>
    <script>
        const $app = document.querySelector("#app");
        const $li = document.createElement("li");
        $li.appendChild(document.createTextNode("c"));
        $app.insertBefore($li, $app.lastElementChild);  
    </script>
</body>

반드시 insertBefore 메소드를 호출한 노드의 자식노드여야 한다.

노드 복사

API 설명
cloneNode 노드의 사본을 생성하여 반환한다. 매개변수에 true 를 전달시 노드를 깊은 복사하여 모든 자손이
생성된 사본을 생성하고 false 시 얉은복사하여 자신의 사본만 전달된다. default : false
<body>
    <ul id="app">
        <li>red</li>
    </ul>
    <script>
        const $app = document.querySelector("#app");
        const $shallowClone = $app.firstElementChild.cloneNode();
        $shallowClone.textContent = "blue";
        $app.appendChild($shallowClone);

        const $deepClone = $app.cloneNode(true);
        $app.appendChild($deepClone);
    </script>
</body>

노드 교체

API 설명
replaceChild 자신이 호출한 노드의 자식노드를 다른 노드로 교체한다. 
첫 번째 인자로 교체할 새로운 노드를, 두 번째 인자로 교체될 노드를 전달한다.
<body>
    <ul id="app">
        <li>red</li>
    </ul>
    <script>
        const $app = document.querySelector("#app");
        const $newNode = document.createElement("li");
        $newNode.appendChild(document.createTextNode("new Red"));

        $app.replaceChild($newNode, $app.firstElementChild);
    </script>
</body>

노드 제거

API 설명
removeChild 인수로 전달한 노드를 DOM 에서 제거한다. 
인수로 전달한 노드는 호출한 노드의 자식 노드여야한다.
remove 본인까지 포함하여 해당 돔을 완전히 제거해버린다. 

removeChild

<body>
    <ul id="app">
        <li>red</li>
        <li>blue</li>
    </ul>
    <script>
        const $app = document.querySelector("#app");
        $app.removeChild($app.lastElementChild); // #li blue 노드 삭제
    </script>
</body>

자식노드 전부 제거 방법

<body>
    <ul id="app">
        <li>red</li>
        <li>blue</li>
    </ul>
    <script>
        const $app = document.querySelector("#app");
        while($app.hasChildNodes()){
            $app.removeChild($app.firstChild);
        }
    </script>
</body>

innerHTML 을 사용한 방법

<body>
    <ul id="app">
        <li>red</li>
        <li>blue</li>
    </ul>
    <script>
        const $app = document.querySelector("#app");
        $app.innerHTML ="";
    </script>
</body>

remove

<body>
    <ul id="app">
        <li>red</li>
        <li>blue</li>
    </ul>
    <script>
        const $app = document.querySelector("#app");

        $app.remove(); // 본인까지 포함하여 삭제
    </script>
</body>

Reference

  • 모던 자바스크립트 - 이웅모

There might be incorrect information or outdated content.

'Web > Javascript' 카테고리의 다른 글

[JAVASCRIPT] try-catch 에러 전파  (0) 2023.08.15
[JAVASCRIPT] isNaN 검사  (0) 2023.08.15
[JAVASCRIPT] DOM - 노드 탐색  (0) 2023.08.04
[JAVASCRIPT] DOM - 노드 취득 (HTMLCollection)  (0) 2023.08.04
[JAVASCRIPT] Full Screen  (0) 2023.07.29