Не удалось выполнить «removeChild» на «Узле»: параметр 1 не относится к типу «Узел». (он удаляет элементы из dom, но только один раз)

#javascript #css #reactjs #dom #frontend

Вопрос:

Это немного сложная задача !!! Я знаю, что раньше задавалось много таких вопросов, но все они предназначены для конкретных случаев.

Я создаю игру tictactoe, используя шаблон дизайна модуля. Я использую функцию ниже, чтобы создать две функции, которые отображают X amp; O, а также добавляют их в dom. Функция gameFlow находится в сетинтервале, поэтому всякий раз, когда игроки нажимают на dom, отображаются x и o. Функция также получает доску из модуля игровой доски ( который также находится ниже), а затем добавляет X amp; O на доску.

 const gameFlow = () =gt; {  const board = gameBoard.getBoard()  const box = document.querySelectorAll('.gameBox')  let x = true // Put this in the global scope if there is an error.   const renderX = (e) =gt; {  for (let i = 0; i lt; board.length; i  ) {  const target = e.target  const data = target.getAttribute('data-index')  const el = document.createElement('p')  el.classList.add('elstyle')  if (board[i] === '') {  if (i === Number(data)) {  gameBoard.fillBoard(i, 1, '❌')  el.textContent = `${board[i]}`  target.appendChild(el)  x = false  }   }  }  }   const renderO = (e) =gt; {  for (let i = 0; i lt; board.length; i  ) {  const target = e.target  const data = target.getAttribute('data-index')  const el = document.createElement('p')  el.classList.add('elstyle')  if (board[i] === '') {  if (i === Number(data)) {  gameBoard.fillBoard(i, 1, '⭕')  el.textContent = `${board[i]}`  target.appendChild(el)  x = true  }   }  }  }   box.forEach(el =gt; el.addEventListener('click', ((e) =gt; {  if (x) {  renderX(e)  } else {  renderO(e)  }  }))) }  

Ниже приведен модуль игровой доски. Как показано в функции gameFlow, 2 функции в игровой доске также заполняют массив доски. Xs и Os затем отображаются в dom путем итерации по массиву платы.

 const gameBoard = (() =gt; {  let board = [  '', '', '',  '', '', '',  '', '', ''  ]   const getBoard = () =gt; {  return board  }   const fillBoard = (index, count, el) =gt; {  board.splice(index, count, el)  }   const resetBoard = () =gt; {  board.splice(0, board.length)  }   const setBoard = () =gt; {  board = [  '', '', '',  '', '', '',  '', '', ''  ]  }   return {getBoard, fillBoard, resetBoard, setBoard} })()  

И, наконец, ниже приведен модуль перезапуска, в котором регистрируется ошибка.

 const restartGame = (() =gt; {  const mainThree = document.getElementById('mainThree')  const restart = document.getElementById('restartBtn')  const boxes = document.querySelectorAll('.gameBox')   restart.addEventListener('click', () =gt; {  mainThree.style.display = 'none'  // gameBoard.resetBoard()  gameBoard.setBoard()  boxes.forEach(el =gt; el.removeChild(el.firstChild))  }) })()  

Таким образом, всякий раз, когда я перезапускаю игру, элементы в dom (Xs и Os) удаляются из dom (но ошибка регистрируется в консоли). Но когда я играю снова и после перезагрузки, элементы очищаются или некоторые элементы очищаются (удаляются), а некоторые нет.

вот ссылка на полную app.js файл. [введите описание ссылки здесь][1] [1]: https://github.com/rabtennamgyal/TOP-Project-tictactoe/blob/main/app.js

Спасибо за всю помощь.

Блок-цитата

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

1. Не уверен, что в этом проблема, но … restartGame добавляет новый прослушиватель событий щелчка каждый раз, когда он вызывается, без удаления добавленных предыдущих прослушивателей. Попробуйте определить обработчик щелчка в именованной функции или нелокальной переменной и удалить его перед добавлением заново или просто добавьте его только один раз.

Ответ №1:

В вашем коде перезапуска boxes.forEach(el =gt; el.removeChild(el.firstChild)) вызывается для каждого элемента с классом gameBox . Однако только у некоторых из этих элементов есть дочерние элементы (X и O, которые воспроизводятся во время игры)gt; Так что в некоторых случаях gt; el.firstChild есть null . Следовательно, вы пытаетесь позвонить el.removeChild(null) , что приводит к ошибке, потому null что это не узел. Чтобы исправить это, вы должны проверить, существует ли el.firstChild, и вызывать removeChild только в том случае, если он не равен нулю.

Ответ №2:

Спасибо вам обоим за то, что помогли мне. Я решил эту проблему, создав новую функцию, которая удаляет каждый элемент dom. Я думаю, что ошибка заключалась в том, что при каждой сыгранной игре Xs и Os добавляются в dom, и поскольку Xs и Os можно воспроизводить в разных коробках во время разных игр; некоторые коробки содержат два элемента, в то время как другие только один и т. Д. Поэтому раньше я удалял только первого ребенка, отсюда и ошибка. Я должен удалить каждого ребенка. Чтобы я использовал код

 for (let i = 0; i lt; boxes.length; i  ) {  while (boxes[i].firstChild) {  boxes[i].removeChild(boxes[i].firstChild);  }  }   
 const restartGame = (() =gt; {  const mainThree = document.getElementById('mainThree')  const restart = document.getElementById('restartBtn')  const boxes = document.querySelectorAll('.gameBox')   function goAgain() {  mainThree.style.display = 'none'  // gameBoard.resetBoard()  gameBoard.setBoard()   for (let i = 0; i lt; boxes.length; i  ) {  while (boxes[i].firstChild) {  boxes[i].removeChild(boxes[i].firstChild);  }  }  }   restart.addEventListener('click', goAgain) })()   

Спасибо вам обоим за вашу помощь. Мир