Как добавить HTML-код с помощью JavaScript?

Я пытаюсь добавить элемент в DOM с помощью JavaScript. У меня есть ul, и я хочу добавить li. В использовании appendChild нет ничего сложного, но я хочу, чтобы мой li был более сложным.

Это результат, которого я пытаюсь достичь:

<li>
  <span class="author">Me</span>
  <span class="message">Message...</span>
  <span class="time">
    <div class="line"></div>
    15:21
  </span>
</li>
let author = "me";
let message = "Message...";
let time = "15:21";

Как видите, я пытаюсь создать не просто li с некоторым текстом (innerHTML), но довольно большой кусок HTML-кода.

Мой вопрос в том, как я могу добиться этого вывода с помощью JavaScript. Или я должен использовать какую-то библиотеку JavaScript или что-то еще, чтобы упростить задачу?


person Michal K    schedule 17.03.2020    source источник
comment
Пожалуйста, опубликуйте свою попытку. Если вы нажмете изменить, а затем [<>] редактор фрагментов, вы можете дать нам минимальный воспроизводимый пример   -  person mplungjan    schedule 17.03.2020
comment
В чем проблема с .appendChild()? Создайте <li> со всеми его дочерними элементами, а затем просто добавьте <li>   -  person Andreas    schedule 17.03.2020
comment
Но, в конце концов, это все еще недопустимая разметка. <div> не является дочерним элементом <span>   -  person Andreas    schedule 17.03.2020
comment
зачем вам помещать ‹div› в ‹span›?? span — это встроенный элемент, а div — это блочный элемент. это плохой код   -  person Iamnino    schedule 17.03.2020
comment
@Andreas Андреас Я все еще младший разработчик, и я думал, есть ли лучшее решение для моей проблемы. Как JSX в React, чтобы я мог писать HTML внутри javascript. И спасибо, что рассказали мне о <span>.   -  person Michal K    schedule 17.03.2020
comment
div является вполне допустимым дочерним элементом в диапазоне, при условии, что его свойство CSS display установлено на inline.   -  person Teemu    schedule 17.03.2020
comment
Более важный вопрос: почему OP использует <div> в качестве презентационного элемента (выведенного из имени его класса) вместо CSS?   -  person David says reinstate Monica    schedule 17.03.2020
comment
ты видел мой ответ? (с DOMParser)   -  person Mister Jojo    schedule 17.03.2020


Ответы (5)


Взгляните на эта исходная ссылка для того кода, куда мы добавляем DOM. Затем вы можете использовать интерполяцию строк, чтобы добавить переменные в код, как показано ниже.

function appendHtml(el, str) {
  var div = document.createElement('div'); //container to append to
  div.innerHTML = str;
  while (div.children.length > 0) {
    el.appendChild(div.children[0]);
  }
}

let author = "me";
let message = "Message...";
let time = "15:21";

var html = `<li><span class="author">${author}</span><span class="message">${message}</span><span class="time"><div class="line"></div>${time}</span></li>`;
appendHtml(document.body, html);

person PEPEGA    schedule 17.03.2020
comment
Спасибо, это именно то, что я искал. - person Michal K; 17.03.2020
comment
Однако он создает недопустимый HTML, поскольку элемент <li> имеет только <ul> или <ol> в качестве допустимого родительского элемента. - person David says reinstate Monica; 17.03.2020
comment
@MichalK Итак, .appendChild() это решение? Вы также уже упоминали .innerHTML. Итак, оба шага, которые этот ответ использует для решения вашей проблемы. Как это может быть ответом? о.О - person Andreas; 17.03.2020
comment
@Andreas, я думаю, что оператор искал интерполяцию строк - person PEPEGA; 17.03.2020
comment
@DavidsaysreinstateMonica Ну, это не имеет значения, не так ли? Просто взял то, что хотел оператор вывода, и применил его. - person PEPEGA; 17.03.2020
comment
Нет, я так не думаю. Цель сайта — сделать интернет лучше и научить делать что-то лучше. Создание недопустимого HTML - даже без указания этой проблемы в ответе - кажется плохой практикой. Но это ваш ответ, и вы имеете полное право не согласиться со мной. - person David says reinstate Monica; 17.03.2020

Если вы хотите вставить строку html-элементов в качестве html-узла, вам нужно создать html-элементы для использования с appendChild().

Однако insertAdjacentHTML() позволяет добавлять элементы html, если они переданы в виде строки. https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentHTML

let author = "me";
let message = "Message...";
let time = "15:21";
let str = `<li><span class="author">${author}</span><span class="message">${message}</span><span class="time"><div class="line"></div>${time}</span></li>`;
document.querySelector('#nav').insertAdjacentHTML('beforeend', str);
<ul id='nav'><ul>

let html = `<li>
  <span class="author">Me</span>
  <span class="message">Message...</span>
  <span class="time">
    <div class="line"></div>
    15:21
  </span>
</li>`;
document.querySelector('#list').insertAdjacentHTML('beforeend', html);
<ul id='list'></ul>

person Umair Khan    schedule 17.03.2020
comment
Во втором примере нет смысла использовать литерал шаблона. - person Andy; 17.03.2020
comment
@Andy Энди, я использовал литерал шаблона для работы с новой строкой / разрывами строк. - person Umair Khan; 17.03.2020

Вы можете использовать литерал шаблона и insertAdjacentHTML для чистого подхода.

function createListItem({ author, message, time }) {
  return `<li>
    <span class="author">${author}</span>
    <span class="message">${message}</span>
    <span class="time">
      <div class="line"></div>
      ${time}
    </span>
  </li>`;
}

const ul = document.querySelector('ul');

ul.insertAdjacentHTML('beforeend', createListItem({
  author: 'me',
  message: 'Message...',
  time: '15:21'
}));
.line { display: inline };
<ul>
  <li>Current</li>
</ul>

person Andy    schedule 17.03.2020

более простой, (для меня)

const DomParser = new DOMParser()

function makeLI( author, message, time)
  {
  let ElemLI =
    `<li>
      <span class="author">${author}</span>
      <span class="message">${message}</span>
      <span class="time">
        <div class="line"></div>
        ${time}
      </span>
    </li>`
  return (DomParser.parseFromString( ElemLI, 'text/html')).body.firstChild
  }


// proof...
myList.appendChild(makeLI('you','Message...','15:21'))
myList.appendChild(makeLI('me','someone in ?','21:25'))
<ul id="myList"></ul>

person Mister Jojo    schedule 17.03.2020

Вот небольшая хитрость, которую вы можете использовать.

На самом деле вы можете использовать существующий DOM (HTML) в качестве своего рода шаблона, в основном клонировать элемент, а затем заменять части нужными вам значениями.

Сначала вы удаляете элемент из DOM с помощью удаления, хотя элемент был удален из DOM, это не мешает вам клонировать его.

Теперь, когда вам понадобится еще один, вызовите clone(true), true = deepClone, и с помощью querySelector замените части DOM нужными вам битами. Наконец, добавьте этот клонированный элемент в DOM.

Ниже приведен простой пример..

const ol = document.querySelector('ol');
const template = document.querySelector('li');
template.remove();

function append(o) {
  const {author, message, time} = o;
  const clone = template.cloneNode(true);
  clone.querySelector('.author').innerText=author;
  clone.querySelector('.message').innerText=message;
  clone.querySelector('.time').lastChild.nodeValue=time;
  ol.appendChild(clone); 
}

append({
  author: "me",
  message: "Message...",
  time: "15:21"
});

append({
  author: "Another me",
  message: "Something else..",
  time: "12:42"
});

append({
  author: "Whatever",
  message: "lalala..",
  time: "17:20"
});
.author {
  font-weight: bold;
  margin-right: 1rem;
}
.time {
  color: green;
}
li {
  margin: 0.5rem;
  border: 1px solid silver;
}
.line {
  border-bottom: 1px dotted red;
}
<ol>
  <li>
    <span class="author">Me</span>
    <span class="message">Message...</span>
    <span class="time">
      <div class="line"></div>
      15:21
    </span>
  </li>
</ol>

person Keith    schedule 17.03.2020