Наиболее эффективный способ создания div с несколькими дочерними элементами

#javascript #html #createelement #template-literals

Вопрос:

Я пытаюсь создать функцию, которая принимает объект с несколькими параметрами и возвращает вновь созданный div.

Из того, что я вижу, кажется, есть два основных способа добиться этого:

  • создание каждого отдельного элемента и его добавление
  • создаем литерал шаблона и устанавливаем divs innerHTML

входные данные функций не генерируются пользователем, поэтому я не думаю, что использование литералов шаблонов создаст проблему безопасности (пожалуйста, просветите меня, если я ошибаюсь)

Итак, теперь мои вопросы следующие:

  • является ли один более эффективным, чем другой?
  • какой из них предпочтительнее?
  • есть ли какие-либо другие проблемы?
  • есть ли еще более эффективный / лучший способ?

ниже вы можете увидеть два решения, которые я придумал.

 function createDiv (entry) {
  const div = document.createElement('div')
  div.classList.add('exchange')
  div.id = entry.exchange
  const img = document.createElement('img')
  img.src = `/static/img/${entry.img}.png`
  img.alt = entry.name
  img.classList.add('logo-image')
  div.appendChild(img)
  const link = document.createElement('a')
  link.href = entry.url
  link.classList.add('name')
  link.innerText = entry.name
  div.appendChild(link)
  const routing = document.createElement('span')
  routing.innerText = entry.routing ? entry.routing : ''
  div.appendChild(routing)
  const price = document.createElement('span')
  price.innerText = entry.price
  price.classList.add('price')
  div.appendChild(price)
  return div
}

function createDiv (entry) {
  const div = document.createElement('div')
  div.classList.add('exchange')
  div.id = entry.exchange

  let text = `
    <img class="logo-image" src="/static/img/${entry.img}.png" alt="${entry.name}">
    <a class="exchange-name" href="${entry.url}">${entry.name}</a>
    <span>${routing.innerText = entry.routing ? entry.routing : ''}</span>
    <span class="price">${entry.price}</span>
  `
  div.innerHTML = text
  return div
}
 

Заранее благодарю вас!

Комментарии:

1. Ваш первый пример использования createElement , хотя и более подробный, предпочтительнее, особенно если входные данные поступают от пользователя.

2. очевидно, что наибольшая проблема была XSS бы. Я бы настоятельно рекомендовал дезинфицировать независимо от того, кто генерирует контент. не сегодня, не завтра, но когда-нибудь новый разработчик посмотрит на код и скажет hey, why not pass a script to show that alert product team wants , и все пойдет к sh1t.

3. Извините, там была опечатка: она не сгенерирована пользователем.

4. Другим подходом может быть использование шаблона , а затем замена необходимых значений.

Ответ №1:

Как насчет того, чтобы сделать что-то вроде следующего?

 const createDiv = ({ exchange, img, name, url, routing: entryRouting, price }) => {      
  return `
  <div class="exchange" id="${exchange}">
    <img class="logo-image" src="/static/img/${img}.png" alt="${name}">
    <a class="exchange-name" href="${url}">${name}</a>
    <span>${routing.innerText = entryRouting || ''}</span>
    <span class="price">${price}</span>
   </div>
  `;
} 

В этом случае вы получаете полную мощность литералов шаблона и уничтожения объекта.

Что касается значений, вы должны каким-то образом проверить их перед сохранением в базе данных и очистить HTML-код перед его возвратом. Для проверки может быть достаточно какой-то простой проверки с помощью регулярных выражений. Для очистки вы можете выбрать одну из многих библиотек, подобных this https://www.npmjs.com/package/sanitize-html .

Что касается производительности, я бы не стал воспринимать это слишком серьезно, пока вы не выполните много итераций. Насколько я вижу, это одноразовый вызов функции. Поэтому я бы выбрал более чистый способ: строки шаблонов. Но если вам интересно, строка шаблона является самой быстрой. Первый подход почти на 100% медленнее. Вы можете проверить результаты теста, который я провел более 100 итераций здесь https://jsbench.me/7gkw1t31rs/2 .

Помните, что подход, о котором я вам рассказываю, потребует innerHTML, как только функция createDiv вернет свое значение.

Комментарии:

1. Потрясающе, спасибо! Функция может вызываться довольно много раз, когда на странице много элементов. Но, похоже, это правильный путь! Мне определенно нужно научиться тестировать код для себя, jsbench.me похоже, это потрясающий ресурс!

2. Я рад, что помог вам с этим. JSBench — это самый быстрый способ понять, какая реализация является самой быстрой. Но вы всегда должны думать и о чистом коде, поэтому ваш код должен быть понятным и понятным. Увидимся в следующий раз!

3. Быстрое обновление: я добавил создание div в литеральную функцию шаблона, просто чтобы сделать тест более справедливым. С дополнительным document.createElement вторая функция на самом деле примерно на 20% медленнее. Я все же мог бы сохранить буквальную функцию шаблона, поскольку она намного более удобочитаема и лаконична.