실제로 innerHTML보다 createElement를 사용하면 어떤 이점이 있습니까? innerHTML을 사용하는 것이 성능 및 코드 가독성 / 유지 보수 측면에서 더 효율적이라고 확신하기 때문에 질문하고 있지만 팀원들은 코딩 접근 방식으로 createElement를 사용하기로 결정했습니다. createElement가 어떻게 더 효율적일 수 있는지 이해하고 싶습니다.
답변:
Pekka가 이미 언급했듯이 안전 외에도 createElement
수정 innerHTML
(이미있는 것을 버리고 교체하는 것과는 반대로) 대신 사용 하는 데는 몇 가지 이점이 있습니다 .
에 추가 (또는 수정) 할 때 innerHTML
해당 요소 내의 모든 DOM 노드를 다시 구문 분석하고 다시 만들어야합니다. 노드에 대한 참조를 저장하면 더 이상 표시되지 않기 때문에 본질적으로 쓸모가 없습니다.
이것은 마지막 경우의 특별한 경우 (일반적이지만)입니다. 설정 innerHTML
은 생성 된 새 요소에 이벤트 핸들러를 자동으로 다시 연결하지 않으므로 직접 추적하고 수동으로 추가해야합니다. 이벤트 위임은 경우에 따라이 문제를 해결할 수 있습니다.
많은 추가 작업을 수행하는 경우, innerHTML
단순한 변경의 경우 더 빠르지 만 반복적으로 다시 구문 분석하고 요소를 만드는 속도가 더 느리기 때문에 재설정을 계속하고 싶지는 않습니다 . 이 문제를 해결하는 방법은 HTML을 문자열로 작성하고 innerHTML
완료되면 한 번 설정 하는 것입니다. 상황에 따라 문자열 조작은 단순히 요소를 만들고 추가하는 것보다 느릴 수 있습니다.
또한 문자열 조작 코드가 더 복잡 할 수 있습니다 (특히 안전을 원하는 경우).
다음은 사용하기 더 편리하도록 가끔 사용하는 기능 createElement
입니다.
function isArray(a) {
return Object.prototype.toString.call(a) === "[object Array]";
}
function make(desc) {
if (!isArray(desc)) {
return make.call(this, Array.prototype.slice.call(arguments));
}
var name = desc[0];
var attributes = desc[1];
var el = document.createElement(name);
var start = 1;
if (typeof attributes === "object" && attributes !== null && !isArray(attributes)) {
for (var attr in attributes) {
el[attr] = attributes[attr];
}
start = 2;
}
for (var i = start; i < desc.length; i++) {
if (isArray(desc[i])) {
el.appendChild(make(desc[i]));
}
else {
el.appendChild(document.createTextNode(desc[i]));
}
}
return el;
}
다음과 같이 부르면 :
make(["p", "Here is a ", ["a", { href:"http://www.google.com/" }, "link"], "."]);
다음과 같은 HTML을 얻을 수 있습니다.
<p>Here is a <a href="http://www.google.com/">link</a>.</p>
make
함수가 조금 더 쉽게 만들 수있는 또 다른 것 ).
innerHTML
단점 때문에 피 합니다. 복잡한 마크 업 (예 : 테이블 작성)의 경우 일반적으로 마크 업의 각 부분을 생성하는 함수를 작성합니다. 예를 들어, tr
각 행의 데이터에서 를 생성하는 함수가 있습니다 . 그런 다음 행을 테이블로 결합하는 다른 기능이있을 수 있습니다. 각 함수 make
는 적절한 인수 로 호출 하는 것처럼 간단 할 수 있습니다 . 성능이 문제가되면 HTML 문자열을 반환하도록 함수를 변경할 수 있습니다.
innerHTML
더 빠를 수 있지만 가독성이나 유지 관리 측면에서 더 좋다는 데 동의하지 않습니다. 모든 것을 하나의 문자열에 넣는 것이 더 짧을 수 있지만 코드가 짧다고 항상 유지 관리가 더 쉬운 것은 아닙니다.
문자열 연결은 더하기 '와 따옴표 열기 및 닫기를 추적하기 어려워 지므로 동적 DOM 요소를 만들어야하는 경우에만 확장되지 않습니다. 다음 예를 고려하십시오.
결과 요소는 콘텐츠가 동적 인 두 개의 내부 범위가있는 div입니다. 첫 번째 범위 내의 클래스 이름 (전사) 중 하나도 동적입니다.
<div>
<span class="person warrior">John Doe</span>
<span class="time">30th May, 2010</span>
</div>
다음 변수가 이미 정의되어 있다고 가정합니다.
var personClass = 'warrior';
var personName = 'John Doe';
var date = '30th May, 2010';
innerHTML 만 사용하고 모든 것을 단일 문자열로 매싱하면 다음을 얻을 수 있습니다.
someElement.innerHTML = "<div><span class='person " + personClass + "'>" + personName + "</span><span class='time'>" + date + "</span></div>";
위의 혼란은 매번 문자열을 열고 닫지 않도록 문자열 교체를 사용하여 정리할 수 있습니다. 간단한 텍스트 교체의 경우에도 replace
문자열 연결 대신 사용 하는 것을 선호합니다 .
이것은 키와 대체 값의 객체를 가져와 문자열에서 대체하는 간단한 함수입니다. 키가 $
특수 값임을 나타 내기 위해 접두사가 붙은 것으로 가정합니다 . $
대체 값 등에 나타나는 이스케이프 또는 가장자리 케이스를 처리하지 않습니다 .
function replaceAll(string, map) {
for(key in map) {
string = string.replace("$" + key, map[key]);
}
return string;
}
var string = '<div><span class="person $type">$name</span><span class="time">$date</span></div>';
var html = replaceAll(string, {
type: personClass,
name: personName,
date: date
});
someElement.innerHTML = html;
객체를 구성하는 동안 속성, 텍스트 등을 분리하여 요소 구성을보다 프로그래밍 방식으로 제어함으로써 개선 할 수 있습니다. 예를 들어 MooTools를 사용하면 객체 속성을 맵으로 전달할 수 있습니다. 이것은 확실히 더 유지 관리가 가능하며 더 읽기 쉽다고 주장합니다. jQuery 1.4는 유사한 구문을 사용하여 DOM 객체를 초기화하기위한 맵을 전달합니다.
var div = new Element('div');
var person = new Element('span', {
'class': 'person ' + personClass,
'text': personName
});
var when = new Element('span', {
'class': 'time',
'text': date
});
div.adopt([person, when]);
아래의 순수한 DOM 접근 방식을 위의 것보다 더 읽기 쉽게 부르지는 않겠지 만 여는 / 닫는 따옴표와 수많은 더하기 기호를 추적 할 필요가 없기 때문에 확실히 유지 관리가 더 쉽습니다.
var div = document.createElement('div');
var person = document.createElement('span');
person.className = 'person ' + personClass;
person.appendChild(document.createTextNode(personName));
var when = document.createElement('span');
when.className = 'date';
when.appendChild(document.createTextNode(date));
div.appendChild(person);
div.appendChild(when);
가장 읽기 쉬운 버전은 일종의 자바 스크립트 템플릿 을 사용한 결과 일 가능성이 큽니다 .
<div id="personTemplate">
<span class="person <%= type %>"><%= name %></span>
<span class="time"><%= date %></span>
</div>
var div = $("#personTemplate").create({
name: personName,
type: personClass,
date: date
});
var a = hello
.하지만 귀하의 코드를 알아낼 수 있습니다. 하나의 연결된 문자열보다 더 읽기 쉬워 보입니다.
innerHTML
더 빨리? jsperf.com/innerhtml-vs-createelement-and-appendchild
사용자 bobince 는 jQuery에 대한 그의 비판 에서 여러 가지 단점을 매우 잘 설명 합니다.
... 또한 document.createElement ( 'div') 및 텍스트 노드를 사용하지 않고 $ ( "+ message + '')라고 말하여 div를 만들 수 있습니다. 만세! 단지 ... 잠시만 요. HTML에서 벗어나지 않았고 이번에는 클라이언트 측에서만 크로스 사이트 스크립팅 보안 허점을 만들었을 것입니다. 그리고 서버 측에서도 htmlspecialchars를 사용하기 위해 PHP를 너무 오랫동안 정리 한 후에. 부끄러운 일입니다. 아 글쎄, 아무도 정확성이나 보안에 대해 정말로 신경 쓰지 않습니까?
jQuery는 이것에 대해 전적으로 책임이 없습니다. 결국 innerHTML 속성은 몇 년 동안 사용되어 왔으며 이미 DOM보다 더 인기가 있음이 입증되었습니다. 그러나 라이브러리는 확실히 그러한 코딩 스타일을 장려합니다.
성능에 관해서 : InnerHTML은 파싱되고 내부적으로 DOM 요소로 변환되어야하기 때문에 (아마도createElement
메서드를 ) 입니다.
InnerHTML은 다음에 따라 모든 브라우저에서 더 빠릅니다. 제공 quirksmode 벤치 마크 .
가독성 과 사용 편의성에 관해서 는 대부분의 프로젝트에서 요일을 선택 innerHTML
하는 것이 createElement
좋습니다. 그러나 보시다시피 createElement
.
innerHTML
? 나는 그것이 확실히 거짓이라는 것을 오랫동안 알고 있습니다. innerHTML
실제로 사용 하는 것은 일부 브라우저 (추측)의 극적인 성능 이점 때문에 프레임 워크 내부에서 인기를 얻었습니다.
createElement
. 이것은 첫 단계에서하는 일이다. 그렇지 않다고 말하는 벤치 마크를 알고 있다면 기꺼이 바로 잡을 것입니다.
코드에서 참조를 유지하려면 createElement를 사용해야합니다. InnerHTML은 때때로 발견하기 어려운 버그를 생성 할 수 있습니다.
HTML 코드 :
<p id="parent">sample <span id='test'>text</span> about anything</p>
JS 코드 :
var test = document.getElementById("test");
test.style.color = "red"; //1 - it works
document.getElementById("parent").innerHTML += "whatever";
test.style.color = "green"; //2 - oooops
1) 색상을 변경할 수 있습니다.
2) 위의 줄에서 innerHTML에 무언가를 추가하고 모든 것이 다시 생성되고 더 이상 존재하지 않는 것에 액세스 할 수 있기 때문에 더 이상 색상이나 다른 것을 변경할 수 없습니다. 변경하려면 다시 getElementById 해야합니다 .
모든 이벤트에도 영향을 미친다는 점을 기억해야합니다. 이벤트를 다시 신청해야합니다.
InnerHTML은 더 빠르고 읽기가 더 쉬우므로 훌륭하지만주의해서 사용해야합니다. 당신이 무엇을하고 있는지 안다면 당신은 괜찮을 것입니다.
템플릿 리터럴 (템플릿 문자열)은 또 다른 옵션입니다.
const container = document.getElementById("container");
const item_value = "some Value";
const item = `<div>${item_value}</div>`
container.innerHTML = item;