Застрял с манипуляцией JS DOM

1

Я застрял в этой простой манипуляции JS DOM. Ниже приведена моя разметка HTML. Я пытаюсь динамически генерировать отдельные элементы списка с помощью JS.

Моя проблема: каждый отдельный тег Span должен содержать отдельный элемент из массива объектов, но в моем случае один тег span содержит все элементы. Как я могу заставить его работать? Я знаю, что это должно быть что-то очень простое, но я не мог понять, где я здесь не прав?

HTML-код:

<ul class="collection" id="web-book-list">
            <li class="collection-item">
              <span class="flow-text">item 1</span>
              <a href="#!" class="secondary-content"
                ><i class="small material-icons black-text">visibility</i></a
              >
              <a href="#!" class="secondary-content"
                ><i class="small material-icons red-text">delete_forever</i></a
              >
            </li>
            <li class="collection-item">
              <span class="flow-text">item 2</span>
              <a href="#!" class="secondary-content"
                ><i class="small material-icons black-text">visibility</i></a
              >
              <a href="#!" class="secondary-content"
                ><i class="small material-icons red-text">delete_forever</i></a
              >
            </li>
        </ul>

JS CODE:

let bookList = document.getElementById("web-book-list");
  // Create element
  let li = document.createElement("li");
  let span = document.createElement("span");
  let linkA = document.createElement("a");
  let linkB = document.createElement("a");
  let visible = document.createElement("i");
  let deleteBtn = document.createElement("i");

  // Add classes to elements
  li.className = "collection-item";
  span.className = "flow-text";
  linkA.className = "secondary-content";
  linkB.className = "secondary-content";
  visible.className = "small material-icons black-text";
  deleteBtn.className = "small material-icons red-text";

  // create text nodes
  visible.appendChild(document.createTextNode("visibility"));
  deleteBtn.appendChild(document.createTextNode("delete_forever"));

  linkA.appendChild(visible);
  linkB.appendChild(deleteBtn);

  //Loop through the webBooks

  for (let i = 0; i < webBooks.length; i++) {
    console.log(webBooks[i]);
    span.innerHTML += webBooks[i].name; // Problem is here!

    li.appendChild(span);
    li.appendChild(linkA);
    li.appendChild(linkB);
    bookList.appendChild(li);
  }
  console.log(bookList);
  • 3
    Просто к сведению: «Ниже приведена моя HTML- разметка » Это «разметка». «Уценка» - это другое.
Теги:
dom

3 ответа

0

Вам нужно создать элемент span для каждой книги в цикле. Вам также необходимо создать li и ссылки. Когда вы используете appendChild для добавления элемента, который уже находится в другом месте документа, он перемещается, а не копируется.

Поскольку вы устанавливаете классы для элементов и т.д., cloneNode простой способ создать отдельные для каждой итерации цикла - использовать cloneNode:

let bookList = document.getElementById("web-book-list");
// Create element
let li = document.createElement("li");
let span;                                    // *** No need to create one here
let linkA = document.createElement("a");
let linkB = document.createElement("a");

// ...

for (let i = 0; i < webBooks.length; i++) {
  console.log(webBooks[i]);
  const thisSpan = span.cloneNode(true);     // ***
  thisSpan.innerHTML = webBooks[i].name;     // *** No need for += since we're creating a new span

  const thisLi = li.clone(true);             // ***
  thisLi.appendChild(thisSpan);              // ***
  thisLi.appendChild(linkA.cloneNode(true)); // ***
  thisLi.appendChild(linkB.cloneNode(true)); // ***
  bookList.appendChild(thisLi);              // ***
}

Я также предлагаю не рассматривать текст как HTML, который вы здесь делаете:

thisSpan.innerHTML = webBooks[i].name;

Если это имя имеет < в нем (или даже вредоносный контент скрипта), было бы проблемой рассматривать его как HTML. Вместо:

thisSpan.appendChild(document.createTextNode(webBooks[i].name));
  • 0
    Спасибо TJ! Я смог решить это с помощью cloneNode. Я пытался использовать appendChild(document.createTextNode(webBooks[i].name)); но потом подумал, что это не помогает, поэтому я попытался использовать innerHTML.
0

Удалите += и добавьте использование bookList.appendChild(li.cloneNode(true));

var bookList = document.getElementById("web-book-list");
  // Create element
  var li = document.createElement("li");
  var span = document.createElement("span");
  var linkA = document.createElement("a");
  var linkB = document.createElement("a");
  var visible = document.createElement("i");
  var deleteBtn = document.createElement("i");

  // Add classes to elements
  li.className = "collection-item";
  span.className = "flow-text";
  linkA.className = "secondary-content";
  linkB.className = "secondary-content";
  linkA.href = "#0";
  linkB.href = "#0";
  visible.className = "small material-icons black-text";
  deleteBtn.className = "small material-icons red-text";

  // create text nodes
  visible.appendChild(document.createTextNode("visibility "));
  deleteBtn.appendChild(document.createTextNode("delete_forever"));

  linkA.appendChild(visible);
  linkB.appendChild(deleteBtn);

  //Loop through the webBooks

  for (let i = 0; i < 10; i++) {
    span.innerHTML = "test"+i+ " "; // Problem is here!

    li.appendChild(span);
    li.appendChild(linkA);
    li.appendChild(linkB);
    bookList.appendChild(li.cloneNode(true));
  }
<ul class="collection" id="web-book-list">
            <li class="collection-item">
              <span class="flow-text">item 1</span>
              <a href="#!" class="secondary-content"
                ><i class="small material-icons black-text">visibility</i></a
              >
              <a href="#!" class="secondary-content"
                ><i class="small material-icons red-text">delete_forever</i></a
              >
            </li>
            <li class="collection-item">
              <span class="flow-text">item 2</span>
              <a href="#!" class="secondary-content"
                ><i class="small material-icons black-text">visibility</i></a
              >
              <a href="#!" class="secondary-content"
                ><i class="small material-icons red-text">delete_forever</i></a
              >
            </li>
        </ul>

Не забудьте также href

linkA.href = "#0";
linkB.href = "#0";
  • 0
    Спасибо @HudsonPH, cloneNode работал!
  • 0
    @VisheshThakur, если работа, пожалуйста, нажмите на отметку как ответ, местоположение слева, рядом с голосами "за" и "против".
-2

Вы пробовали javascript =)?

const bookList = document.getElementById("web-book-list");
const webBooks = [
    {name: "wb-1"},
    {name: "wb-2"},
    {name: "wb-3"},
    {name: "wb-4"}
];

for (let i = 0; i < webBooks.length; i++) {
    const li = document.createElement('li');
    li.className = 'collection-item';
    li.innerHTML = '
        <span class="flow-text">${webBooks[i].name}</span>
        <a href="#!" class="secondary-content">
            <i class="small material-icons black-text">visibility</i>
        </a>
        <a href="#!" class="secondary-content">
            <i class="small material-icons red-text">delete_forever</i>
        </a>';
    bookList.appendChild(li);
}

Ещё вопросы

Сообщество Overcoder
Наверх
Меню