Ванильный JS для динамического добавления или удаления полей div

#javascript

#javascript

Вопрос:

При установке флажка я пытаюсь создать поля div, а при снятии флажка удалить его динамически.

Я знаю, что с React я мог бы сделать это за 2 минуты, но я пытаюсь изучить ванильный JS-способ

Текущие проблемы, с которыми я сталкиваюсь:

  1. При установке флажка отображается больше элементов, чем один
  2. При снятии флажка, например, все элементы по-прежнему отображаются.

КОНЕЧНАЯ ЦЕЛЬ: динамически добавлять и удалять поля Div в зависимости от того, что находится в state переменной ( console.log чтобы ее вывод давал указания о том, как правильно она должна выглядеть), а также следить за тем, чтобы никакие дополнительные поля не использовались / не отображались.

 window.onload = () => {
  const checkbox = document.querySelectorAll('.checkbox')
  let state = []

  for (idx of checkbox) {
    idx.addEventListener('change', (e) => {
      if (e.currentTarget.checked === true) {
        state.push(e.currentTarget.id)
        renderOnDom(state, 'add', e.currentTarget.id) // Experimenting
      }
      if (e.currentTarget.checked === false) {
        state = state.filter((item) => item !== e.currentTarget.id)
        renderOnDom(state, 'remove', e.currentTarget.id) // Experimenting
      }
      console.log('state', state)
    })
  }
}

const renderOnDom = (el, option, id) => {
  if (option === 'add') {
    el.map((item, idx) => {
      const div = document.createElement('div')
      div.setAttribute('key', item)
      div.className = 'test'
      div.innerHTML = `Box ${item}`
      document.querySelector('#projects').appendChild(div)
    })
  }

  if (option === 'remove') {
    const test = document.querySelectorAll('.test')
    const prod = document.querySelector('#projects')
    for (const iterator of test) {
      if (iterator.attributes.key.value === id) {
        prod.removeChild(prod.firstChild)
      }
    }
  }
}  
 <input id="id1" data="name1" class="checkbox" type="checkbox" />
      <label for="id1">Test 1</label>

      <input id="id2" data="name2" class="checkbox" type="checkbox" />
      <label for="id2">Test 2</label>

      <input id="id3" data="name3" class="checkbox" type="checkbox" />
      <label for="id3">Test 3</label>

      <div id="projects"></div>  

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

1. «При установке флажка отображается больше элементов, чем один» — потому что вы добавляете каждый элемент в state

2. ? мое состояние, которое console.log оно показывает правильно. Итак, если в состоянии есть 3 элемента, ему необходимо отобразить эти 3, но не дублировать их при рендеринге

3. el является ли «состояние» el.map() (которое, кстати, является неправильным инструментом, проверьте его документацию) перебирает все элементы el и добавляет каждый элемент в el /»state» в DOM ( .createElement() , .appendChild() ) .

Ответ №1:

Привет, я обновил ваш фрагмент, чтобы сделать то, что, как я думаю, вы хотите сделать.

В двух словах, источником истины является state массив. Итак, после любых изменений в нем сбросьте dom с помощью resetDom() , а затем запустите renderOnDom() .

 window.onload = () => {
  const checkbox = document.querySelectorAll('.checkbox')
  let state = []

  for (idx of checkbox) {
    idx.addEventListener('change', (e) => {
      if (e.currentTarget.checked === true) {
        state.push(e.currentTarget.id)
      }
      if (e.currentTarget.checked === false) {
        state = state.filter((item) => item !== e.currentTarget.id)
      }
      renderOnDom(state, e.currentTarget.id)
    })
  }
}
const resetDom = () => {
  const projects = document.querySelector("#projects");
  while (projects.firstChild) {
    projects.removeChild(projects.firstChild)
  }
}
const renderOnDom = (el, id) => {
  resetDom();
  el.forEach((item, idx) => {
    const div = document.createElement('div')
    div.setAttribute('key', item)
    div.className = 'test'
    div.innerHTML = `Box ${item}`
    document.querySelector('#projects').appendChild(div)
  })

}  
 <input id="id1" data="name1" class="checkbox" type="checkbox" />
<label for="id1">Test 1</label>

<input id="id2" data="name2" class="checkbox" type="checkbox" />
<label for="id2">Test 2</label>

<input id="id3" data="name3" class="checkbox" type="checkbox" />
<label for="id3">Test 3</label>

<div id="projects"></div>  

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

1. Чувак, ты потрясающий

2. Спасибо @Marius: D и Андреас — да, поскольку мы ничего не возвращаем, forEach имеет больше смысла !!.

3. спасибо, Андреас, я так привык постоянно реагировать с помощью map