어떻게 HTML 문 자 를 DOM 노드 로 변환 하고 문서 에 동적 으로 추가 합 니까?

머리말
문자열 의 동 태 를 DOM 노드 로 바 꾸 는 것 은 개발 과정 에서 자주 볼 수 있 으 며,특히 템 플 릿 엔진 에 서 는 더욱 불가 하거나 부족 한 기술 입 니 다.
문자열 을 DOM 노드 로 변환 하 는 것 자체 가 어렵 지 않 습 니 다.이 글 은 주로 두 가지 주제 와 관련 됩 니 다.
     1 문자열 을 HTML DOM 노드 로 변환 하 는 기본 방법 및 성능 테스트
     2 동적 으로 생 성 된 DOM 노드 를 문서 에 추가 하 는 방법 및 성능 테스트
본 논문 의 예제:다음 과 같은 코드 세그먼트 가 있다.

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <meta http-equiv="X-UA-Compatible" content="ie=edge">
 <title>Document</title>
</head>
<body>
 <div id='container'>
<!--     div 
 <div class='child'> XXX</div>
 -->
 </div>
</body>
</html>
작업 은 자 바스 크 립 트 함 수 를 작성 하여 텍스트 내용 을 받 아들 이 고 이 텍스트 를 포함 하 는 div 를 동적 으로 생 성하 여 노드 로 돌아 가 는 것 입 니 다.다음은 더 이상 할 말 이 없 으 니 편집장 과 함께 상세 한 소 개 를 살 펴 보 자.
1.1 동적 생 성 노드
1.1.1 innerHTML
첫 번 째 방법 은document.createElement방법 으로 새로운 요 소 를 만 든 다음 innerHTML 을 이용 하여 문자열 을 주입 하고 마지막 으로 firstChild 로 돌아 가 동적 으로 만 든 Node 를 얻 는 것 입 니 다.

 <script>
  function createNode(txt) {
   const template = `<div class='child'>${txt}</div>`;
   let tempNode = document.createElement('div');
   tempNode.innerHTML = template;
   return tempNode.firstChild;
  }
  const container = document.getElementById('container');
  container.appendChild(createNode('hello'));
 </script>
다음은 두 번 째 방법 을 보 겠 습 니 다.
1.1.2 DOMParser
DOMParser 인 스 턴 스 의 parseFromString 방법 은 문자열 을 document 문서 대상 으로 직접 변환 할 수 있 습 니 다.document 이 생기 면 우 리 는 각종 DOM Api 를 이용 하여 조작 할 수 있다.

 function createDocument(txt) {
   const template = `<div class='child'>${txt}</div>`;
   let doc = new DOMParser().parseFromString(template, 'text/html');
   let div = doc.querySelector('.child');
   return div;
  }
  
  const container = document.getElementById('container');
  container.appendChild(createDocument('hello'));
1.1.2 DocumentFragment
DocumentFragment 대상 은 부모 파일 이 없 는 최소 문서 대상 을 표시 합 니 다.이것 은 배열 되 어 있 거나 정리 되 지 않 은 XML 세 션 을 저장 하 는 데 사용 되 는 경 량 판 문서 로 사 용 됩 니 다.가장 큰 차이 점 은 DocumentFragment 가 실제 DOM 트 리 의 일부분 이 아니 기 때문에 DOM 트 리 의 재 렌 더 링 작업(reflow)을 일 으 키 지 않 고 성능 등 문 제 를 일 으 키 지 않 기 때 문 입 니 다.document.createRange().createContextualFragment방법 을 이용 하여 문자열 을 DocumentFragment 대상 으로 직접 바 꿀 수 있 습 니 다.

 function createDocumentFragment(txt) {
   const template = `<div class='child'>${txt}</div>`;
   let frag = document.createRange().createContextualFragment(template);
   return frag;
  }

  const container = document.getElementById('container');
  container.appendChild(createDocumentFragment('hello'));
여기 서 주의해 야 할 것 은 우리 가 생 성 된 DocumentFragment 대상 을 목표 노드 에 직접 삽입 하 는 것 입 니 다.이것 은 자신의 모든 점 을 목표 노드 에 삽입 하고 자신 을 포함 하지 않 습 니 다.저희 도 쓸 수 있어 요.

frag.firstChild
생 성 된 div 를 가 져 옵 니 다.
1.1.3 성능 테스트
아래 에서 우 리 는 아래 세 가지 방법의 성능 을 간단하게 비교 해 보 자.단지 하나의 노드 를 생 성 하 는 것 을 테스트 할 뿐 실제 사용 에서 반드시 실제 적 인 의미 가 있 는 것 은 아니다.
먼저 createNode 를 테스트 합 니 다.

 function createNode(txt) {
   const template = `<div class='child'>${txt}</div>`;

   let start = Date.now();
   for (let i = 0; i < 1000000; i++) {
    let tempNode = document.createElement('div');
    tempNode.innerHTML = template;
    let node = tempNode.firstChild;
   }
   console.log(Date.now() - start);

  }
  createNode('hello');
노드 생 성 테스트 100 만 개,사용 시 6322.
createDocument 를 다시 테스트 합 니 다.

 function createDocument(txt) {
   const template = `<div class='child'>${txt}</div>`;
   let start = Date.now();
   for (let i = 0; i < 1000000; i++) {
    let doc = new DOMParser().parseFromString(template, 'text/html');
    let div = doc.firstChild;
   }
   console.log(Date.now() - start);
  }
 createDocument('hello');
노드 생 성 테스트 100 만 개,사용 시 55188.
마지막 으로 createDocumentFragment 를 테스트 합 니 다.

 function createDocumentFragment(txt) {
   const template = `<div class='child'>${txt}</div>`;
   let start = Date.now();
   for (let i = 0; i < 1000000; i++) {
   let frag = document.createRange().createContextualFragment(template);
   }
   console.log(Date.now() - start);
  }
  createDocumentFragment();
노드 생 성 테스트 100 만 개,사용 시 6210.
createDocumentFragment 방법 과 createNode 방법 은 이번 테스트 에서 막상막하 입 니 다.문서 에 생 성 된 DOM 요 소 를 동적 으로 추가 하 는 방법 을 살 펴 보 겠 습 니 다.
1.2.0 대량 추가 노드
동적 으로 만들어 진 노드 의 대부분 상황 은 문서 에 추가 되 어 표 시 됩 니 다.다음은 우리 가 몇 가지 상용 방안 을 소개 하고 비교 해 보 자.
아래 에 우리 가 대량으로 추가 하 는 방법 은 모두 createDocumentFragment 방법 을 사용한다.
1.2.1 직접 append
직접 append 방법 은 하나의 노드 를 만 들 고 문서 에 추가 하 는 것 입 니 다.물론 이것 은 레이아웃 변 화 를 일 으 켜 성능 이 가장 나 쁜 방법 으로 여 겨 집 니 다.

 const template = "<div class='child'>hello</div>";

  function createDocumentFragment() {


   let frag = document.createRange().createContextualFragment(template);
   return frag;
  }
  // createDocumentFragment();
  const container = document.getElementById('container');
  let start = Date.now();
  for (let i = 0; i < 100000; i++) {
   container.appendChild(createDocumentFragment());
  }
  console.log(Date.now() - start);
위의 코드 는 동적 으로 10 만 개의 노드 를 추가 하 는 것 을 추산 합 니 다.결 과 는 다음 과 같다.

1000 개의 노드 를 테스트 하 는 데 20 밀리초 가 걸 리 고 10000 개의 노드 를 테스트 하 는 데 100001 밀리초 가 걸 리 며 100000 개의 노드 를 테스트 하 는 데 46549 밀리초 가 걸린다.
1.2.2 DocumentFragment
위 에서 우 리 는 DocumentFragment 를 소 개 했 습 니 다.이 를 이용 하여 문자열 을 바 꿉 니 다.다음은 이 대상 을 임시 용기 로 이용 하여 여러 노드 를 한꺼번에 추가 합 니 다.document.createDocumentFragment()방법 을 이용 하여 빈 DocumentFragment 대상 을 만 들 수 있 습 니 다.

    const template = "<div class='child'>hello</div>";

    function createDocumentFragment() {


      let frag = document.createRange().createContextualFragment(template);
      return frag;
    }
    // createDocumentFragment();
    const container = document.getElementById('container');
    let fragContainer = document.createDocumentFragment();
    let start = Date.now();
    for (let i = 0; i < 1000; i++) {
      fragContainer.appendChild(createDocumentFragment());
    }
    container.appendChild(fragContainer);
    console.log(Date.now() - start);
1000 개의 노드 를 테스트 하 는 데 25 밀리초 가 걸 리 고 10000 개의 노드 는 2877 밀리초 가 걸 리 며 100000 개의 노드 브 라 우 저 카드 가 죽 습 니 다.
1.3 소결
몇 가지 방법 을 간단하게 소 개 했 지만 기술적 함량 이 별로 없다.그러나 동적 추가 노드 를 보면 인터넷 에서 말 하 는 DocumentFragment 방법 은 직접 append 보다 성능 이 훨씬 좋다 는 주장 은 제 테스트 장면 에서 성립 되 지 않 습 니 다.
DocumentFragment 의 정확 한 응용 장면 은 가상 DOM 용기 로 서 검색 을 자주 수정 하지만 직접 렌 더 링 할 필요 가 없 는 장면 에서 이 루어 져 야 합 니 다.
총결산
이상 은 이 글 의 전체 내용 입 니 다.본 논문 의 내용 이 여러분 의 학습 이나 업무 에 어느 정도 참고 학습 가치 가 있 기 를 바 랍 니 다.궁금 한 점 이 있 으 시 면 댓 글 을 남 겨 주 셔 서 저희 에 대한 지지 에 감 사 드 립 니 다.

좋은 웹페이지 즐겨찾기