#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) })()
Спасибо вам обоим за вашу помощь. Мир