I have an array of pre-set words that I want to randomize and map whitespace after each entry, then split into individual characters which are then put into an html element as individual <div>. I have this so far which does work but it gets somewhat slow beyond like 150-200 characters which is understandable I guess. I need each character to be in it's own <div> so I'm not sure how to optimize this.
I have an algorithm structure similar to the code snippet below. How do I avoid the optimization issue when rendering lots of dynamic HTML elements in the loop?
let container = document.getElementById('container');
let arr = ['one', 'two', 'three', 'four'];
let currentIndex = arr.length;
let current__text = [], count, randomIndex;
while (currentIndex != 0) {
randomIndex = Math.floor(Math.random() * currentIndex);
--currentIndex;
[current__text[currentIndex], arr[randomIndex]] = [
current__text[randomIndex], arr[currentIndex]];
}
arr = arr.slice(0, count).map(e => e + ' ').join('').split('');
arr.pop();
for (item of arr) {
container.innerHTML += `<div class="char">${item}</div>`;
}
#container{}
.char{}
<div id="container"></div>
Most of the algorithm you developed has no effect on the result. The printArray() method in the solution I developed is equivalent to what you are currently doing.
I added the change specified by @Teemu to the program and compared the results. As @Teemu pointed out, Element.insertAdjacentHTML() method is very fast to Element.innerHTML property. Below is a comparison of the runtimes:
Duration (insertAdjacentHTML): 2.7000000029802322 milliseconds
Duration (innerHTML): 85.70000000298023 milliseconds
NOTE: To compare the runtime differences of the Element.insertAdjacentHTML() method and the Element.innerHTML property, I assign none to the display property of the .char class style, so an element is not printed on the screen.
let container = document.getElementById('container');
let firstArray = [], secondArray = [];
function measurePerformance(method, mode, array){
var startTime = performance.now();
method(mode, array);
var endTime = performance.now();
console.log(`Duration (${mode}): ${endTime - startTime} milliseconds`);
}
function generateArray(firstArray, secondArray){
for(let i = 100 ; i > 50 ; --i){
firstArray.push(i);
secondArray.push(i);
}
}
function printArray(mode, array){
array = array.map(e => e + ' ').join('').split('');
if(mode === "insertAdjacentHTML"){
for(item of array){
container.insertAdjacentHTML("beforeend", `<div class="char">${item}</div>`);
}
}
else if(mode === "innerHTML"){
for(item of array){
container.innerHTML += `<div class="char">${item}</div>`;
}
}
}
generateArray(firstArray, secondArray);
measurePerformance(printArray, "insertAdjacentHTML", firstArray);
measurePerformance(printArray, "innerHTML", secondArray);
.char{
background-color: yellow;
border: 1px solid gray;
margin-bottom: 2px;
display: none;
}
<div id="container"></div>
To create the letters you need this:
arr = ['one', 'two', 'three', 'four'];
const output = arr.map(
(word) => word.trim().split('')
);
console.log(output)
I didn't add HTML part to my answer. If you need help about it, let me know.