Advantages of Createelement Over Innerhtml

Advantages of createElement over innerHTML?

There are several advantages to using createElement instead of modifying innerHTML (as opposed to just throwing away what's already there and replacing it) besides safety, like Pekka already mentioned:

Preserves existing references to DOM elements when appending elements

When you append to (or otherwise modify) innerHTML, all the DOM nodes inside that element have to be re-parsed and recreated. If you saved any references to nodes, they will be essentially useless, because they aren't the ones that show up anymore.

Preserves event handlers attached to any DOM elements

This is really just a special case (although common) of the last one. Setting innerHTML will not automatically reattach event handlers to the new elements it creates, so you would have to keep track of them yourself and add them manually. Event delegation can eliminate this problem in some cases.

Could be simpler/faster in some cases

If you are doing lots of additions, you definitely don't want to keep resetting innerHTML because, although faster for simple changes, repeatedly re-parsing and creating elements would be slower. The way to get around that is to build up the HTML in a string and set innerHTML once when you are done. Depending on the situation, the string manipulation could be slower than just creating elements and appending them.

Additionally, the string manipulation code may be more complicated (especially if you want it to be safe).

Here's a function I use sometimes that make it more convenient to use 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;
}

If you call it like this:

make(["p", "Here is a ", ["a", { href:"http://www.google.com/" }, "link"], "."]);

you get the equivalent of this HTML:

<p>Here is a <a href="http://www.google.com/">link</a>.</p>

Which method is better/ faster for performance - createElement or innerHTML?

There are several advantages to using createElement instead of modifying innerHTML (as opposed to just throwing away what's already there and replacing it) besides safety, like Pekka already mentioned:

Preserves existing references to DOM elements when appending elements

When you append to (or otherwise modify) innerHTML, all the DOM nodes inside that element have to be re-parsed and recreated. If you saved any references to nodes, they will be essentially useless, because they aren't the ones that show up anymore.

Preserves event handlers attached to any DOM elements

This is really just a special case (although common) of the last one. Setting innerHTML will not automatically reattach event handlers to the new elements it creates, so you would have to keep track of them yourself and add them manually. Event delegation can eliminate this problem in some cases.

Could be simpler/faster in some cases

If you are doing lots of additions, you definitely don't want to keep resetting innerHTML because, although faster for simple changes, repeatedly re-parsing and creating elements would be slower. The way to get around that is to build up the HTML in a string and set innerHTML once when you are done. Depending on the situation, the string manipulation could be slower than just creating elements and appending them.

Additionally, the string manipulation code may be more complicated (especially if you want it to be safe).

Here's a function I use sometimes that make it more convenient to use 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;
}

If you call it like this:

make(["p", "Here is a ", ["a", { href:"http://www.google.com/" }, "link"], "."]);

you get the equivalent of this HTML:

<p>Here is a <a href="http://www.google.com/">link</a>.</p>

The answer of @Matthew Crumley

createElement() vs. innerHTML When to use?

Adding to the DOM n times takes n times more time than adding to the DOM a single time. (:P)

This is the logic I'm personally following.

In consequence, when it is about to create, for instance, a SELECT element, and add to it several options, I prefer to add up all options at once using innerHTML than using a createElement call n times.

This is a bit the same as to compare BATCH operation to "one to one"... whenever you can factorise, you should!

EDIT: Reading the comments I understand that there's a feature (DOM DocumentFragment) that allow us saving such overhead and at the same time taking advantage of the DOM encapsulation. In this case, if the performances are really comparable, I would definitely not doubt and chose the DOM option.

Is there a performance enhancement to create dom elements native vs innerHTML?

I suggest to use createElement. It is faster and more secure. Imagine you load user input directly into your DOM with innerHTML. This can be a nasty security hole.

.innerHTML vs. createElement() | setAttribute() vs. Direct*

It's strange that you're putting an A element inside an A element but the below should work.

var c=document.createElement('a');
c.name = "a1";
c.className = "b";
c.href = d[2].value;
c.appendChild(document.createTextNode(d[1].value));

This assumes that d[1].value is not known to be well formed HTML from a trusted source so it is likely to be more robust against XSS than the innerHTML code.

CreateElement and then write innerHTML

There is your snippets using document.createElement, it should work like your version (if on IE you'll probably need to replace textContent by innerText)

function dataPull() {  // Connects to my server from which it pulls JSON data containing start,end,summary,organizer of the event.  fetch("http://localhost:8000/events").then((resp) => resp.json()).then(render)};
function eventFilter(event) { eventTime = new Date(event); eventHours = eventTime.getHours(); eventMinutes = eventTime.getMinutes(); if (eventMinutes < 10) { eventMinutes = "0" + eventMinutes } return eventHours + ":" + eventMinutes;};
function eventMap(eventBooked, classSuffix = "") { event = document.createElement("div") event.classList.add("event")
// create time time = document.createElement("div") time.classList.add("eventTime" + classSuffix) time.textContent = eventFilter(eventBooked.start) // create timep timep = document.createElement("p") timep.classList.add("timep") timep.textContent = eventFilter(eventBooked.end)
// create info info = document.createElement("div") info.classList.add(eventTime) // create summary summary = document.createElement("h1") summary.classList.add("eventSummary" + classSuffix) summary.textContent = eventBooked.summary // create organizer organizer = document.createElement("p") organizer.classList.add("eventOrganizer" + classSuffix) organizer.textContent = eventBooked.organizer
// append everything event.appendChild(time) time.appendChild(timep)
event.appendChild(info) info.appendChild(summary) info.appendChild(organizer)
return event};
function render(data) { data.events.sort(function(a, b) { return new Date(a.start).getTime() - new Date(b.start).getTime(); });
// Delete outdated events. let eventsNotOutdated = data.events.filter((item) => { let endTime = new Date(item.end); if (Date.now() < endTime) { return item; } });
// Create a new variable for event currently in progress. let eventInProgress = eventsNotOutdated.filter((item) => { let startTime = new Date(item.start); if (Date.now() > startTime) { return item; } });
// Same as eventsNotOutdated but without the event in progress. let filteredEventsNotOutdated = eventsNotOutdated.filter((item) => { let startTime = new Date(item.start); if (Date.now() < startTime) { return item; } });
let eventList = document.getElementById("eventList"); for(let child of eventList.children) {eventList.removeChild(child)}
if (eventInProgress.length > 0) { div = document.createElement("div") announcerBig = document.createElement("h1") announcerBig.classList.add("announcerBig") announcerBig.textContent = "In progress" eventBig = eventMap(eventInProgress[0], "Big") div.appendChild(announcerBig) div.appendChild(eventBig) eventList.appendChild(div) if (filteredEventsNotOutdated.length) { inProgress = document.createElement("div") announcer = document.createElement("h1") announcer.classList.add("announcer") announcer.textContent = "Later" inProgress.appendChild(announcer) filteredEventsNotOutdated.forEach(ev => {eventList.appendChild(eventMap(ev))}) eventList.appendChild(inProgress) } } else if (eventInProgress.length === 0 && filteredEventsNotOutdated.length > 0) { announcerBig = document.createElement("h1") announcerBig.classList.add("announcerBig") announcerBig.textContent = "Coming up next" eventList.appendChild(announcerBig) filteredEventsNotOutdated.forEach(ev => {eventList.appendChild(eventMap(ev))}) } else { noevent = document.createElement("p") noevent.classList.add("noevent") noevent.textContent = "No meetings scheduled." schedule = document.createElement("p") schedule.classList.add("schedule") schedule.textContent = "Schedule meetings on google calendars." eventList.appendChild(noevent) eventList.appendChild(schedule) };
return eventList};
setTimeout(dataPull);setInterval(dataPull, 10000);
<html>
<head></head>
<body id='body'> <div id='eventList' class="eventList"></div> <script src="example.js"></script></body>
</html>


Related Topics



Leave a reply



Submit