티스토리 뷰

ES6

6.3DOM과 자바스크립트

✨✨✨✨✨✨✨ 2019. 2. 15. 00:31
반응형

6.3. DOM과 자바스크립트

JS가 DOM을 변경하고 검색할 때,
repaint 또는 reflow가 발생하여,
컴퓨팅 자원 소모가 심해진다.

6.3.1 DOM repaint

가. 정의

DOM위치가 변경되지 않고,
스타일이 변경될 때 화면을 다시 그리는 것

나. 예제(272p)

(function () {
    document.getElementById("changeBackground").addEventListener('click', function () {
        this.style.backgroundColor = "black";
        this.style.color = "white";
    });

    document.getElementById("changeVisibility").addEventListener("click", function () {
        this.style.visibility = "hidden";
    });
}());

img6

위 그림을 비교하였을 때,
JS를 통하여
visibility 혹은 배경색상(스타일)은 수정되었지만,
위치는 변경 안됨.


6.3.2 DOM reflow

가. 정의

DOM위치가 변경되고,
위치에 대한 재계산 과정이 일어나는 것

나. 특징
  • 해당 DOM의 위치가 변경 될 경우, 
    자식 DOM의 위치도 재계산 해야한다. 
    ===> repaint보다 자원 소모가 더 큼

다. 발생 상황
  1. 특정 DOM이 삭제되거나 크기가 변경된 경우
  2. 자바스크립트를 통해 className이 변경된 경우
  3. 브라우저 창 크기가 변경된 경우

다. 예제(275p)

$('#secondDiv').remove();

img7

두번째 DIV가 삭제되면서 세번째 DIV의 위치가 변경됨

6.3.2 reflow, repaint 최소화 방법

1. 크기가 변경될 DOM의 자식 DOM을 최소화


2. position을 이용(279p)

부모부분을 position:relative
위치 고정할 부분을 position:absolute

  • 예제 1)

p_ex_1

  • 예제 2)

p_ex_2


3. position 이용2(283p)

가운데 영역의 최상위 부모를 position:relative 로 잡고
안에 position:absolute로 잡음
목록이 reflow를 일으키지않고 자유롭게 에니메이션 효과


4. JS에서 태그명이 아닌, className, Id로 DOM을 탐색한다.


5. 특정영역에 많은 DIV 추가할 경우, createDocumentFragment 이용(290p)

290

createDocumentFragment을 통한 방법 290p

(function () {
  /**
   * STEP 1. createDocumentFragment생성
   **/
    var fragGuestbook = document.createDocumentFragment();
        inputName = document.getElementById("name"),
        inputSubject = document.getElementById("subject"),
        inputContents = document.getElementById("contents"),
        tbodyGuestbook = document.getElementById("guestbookTbody"),

    /**
     * STEP 2. 담을 객체들 생성
     **/
        trGuestbook = document.createElement("tr"),
        tdName = document.createElement("td"),
        tdSubject = document.createElement("td"),
        tdContents = document.createElement("td");

    /**
     * STEP 3. createDocumentFragment에 객채 담기
     **/
    fragGuestbook.appendChild(trGuestbook);
    trGuestbook.appendChild(tdName);
    trGuestbook.appendChild(tdSubject);
    trGuestbook.appendChild(tdContents);

    document.getElementById("writeForm").addEventListener("submit", function () {
        tdName.innerHTML = inputName.value;
        tdSubject.innerHTML = inputSubject.value;
        tdContents.innerHTML = inputContents.value;

        /**
         * STEP 4. 객체를 담음
         **/
        tbodyGuestbook.appendChild(fragGuestbook.cloneNode(true));
        event.returnValue = false;
        return false;
    });
}());



  • appendChild 예제 295p

(function () {
    var inputName = document.getElementById("name"),
        inputSubject = document.getElementById("subject"),
        inputContents = document.getElementById("contents"),
        divGuestbook = document.getElementById("guestbook"),
        tbodyGuestbook = document.getElementById("guestbookTbody");

    document.getElementById("writeForm").addEventListener("submit", function () {
      /**
       * STEP 1. 담고자하는 객채 생성
       **/
        var trGuestbook = document.createElement("tr"),
            tdName = document.createElement("td"),
            tdSubject = document.createElement("td"),
            tdContents = document.createElement("td");

        tdName.innerHTML = inputName.value;
        tdSubject.innerHTML = inputSubject.value;
        tdContents.innerHTML = inputContents.value;
        trGuestbook.appendChild(tdName);
        trGuestbook.appendChild(tdSubject);
        trGuestbook.appendChild(tdContents);

        /**
         * STEP 2. appendChild()통하여 객채 담기
         **/
        tbodyGuestbook.appendChild(trGuestbook);
        return false;
    });
}());
  • ※ createDocumentFragment() 혹은 appendChild()이용 시,
    한번의 reflow()로 여러개의 객체를 담을 수 있다.


6. clientHeight, offsetWidth등의 스타일 접근을 최소화

7. DOM을 객체로 선언함으로써, 탐색 횟수를 최소화
  • 잘못된 방법

document.getElementById("changeDiv").style.backgroundColor = "#EEE";
document.getElementById("changeDiv").style.fontSize = "10em";
document.getElementById("changeDiv").style.width = "100px";
  • 올바른 방법

var changDivStyle = document.getElementById("changeDiv").style;
changDivStyle.backgroundColor = "#EEE";
changDivStyle.fontSize = "10em";
changDivStyle.width = "100px";

DOM트리를 탐색하는 횟수를 줄여준다.

8. 메모제이션 패턴을 이용

var test = 1 || 2;

가. 정의

함수나 객체를 '메모'하는 것

(function () {
    var memo = {};
    document.getElementById("myForm").onsubmit = function () {
        var inputFirstName = getMemo("firstName"),
            inputMiddleName,
            inputLastName;

        if (inputFirstName.value === "") {
            alert("First name is mandatory");
            inputFirstName.focus();
            return false;
        }

        inputLastName = getMemo("lastName");
    }

    function getMemo(id) {
        memo[id] = memo[id] || document.getElementById(id);
        return memo[id];
    }
}());

getMemo() 함수에서 memo라는 변수를 캐시값에 해두었다가,
메모가 있으면 캐시를 반환
없으면 DOM탐색한다.
입력폼 값을 여러번 검사 하여도 DOM탐색은 한번만 한다.


반응형

'ES6' 카테고리의 다른 글

6.4 웹 워커  (0) 2019.02.15
6.1단일 스레드 환경  (0) 2019.02.15
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/01   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함