无法将子级附加到数组中的每个DOM元素上吗?

时间:2019-05-10 16:59:18

标签: javascript html css

嘿朋友,我有很多要素。我想为每个子元素添加一个子元素。我用了一个for循环

for(let i = 0; i < slots.length; i++) {
    //add class to each div
    slots[i].classList.add('c' + i);
    //add the slot to each div
    slots[i].appendChild(slot);
    //add the function with the game logic to each slot
    slots[i].addEventListener('click', runGame); 
}

并看着每个元素追加孩子。但是,当我查看devtools中的元素时,其中唯一具有跨度的元素是最后一个?不是所有的人?有什么想法吗?

//grab all slot positions on the board
const slots = document.querySelectorAll('.board div');
let player = 'p1';
let board = [
  0, 1, 2, 3, 4, 5, 6,
  7, 8, 9, 10, 11, 12, 13,
  14, 15, 16, 17, 18, 19, 20,
  21, 22, 23, 24, 25, 26, 27,
  28, 29, 30, 31, 32, 33, 34,
  35, 36, 37, 38, 39, 40, 41,
]

let slot = document.createElement('span');


//assign a class to each slot to represent its position
for (let i = 0; i < slots.length; i++) {
  //add class to each div
  slots[i].classList.add('c' + i);
  //add the slot to each div
  slots[i].appendChild(slot);
  //add the function with the game logic to each slot
  slots[i].addEventListener('click', runGame);
}

function runGame() {
  //figure out which column the selected slot sits in
  const slotColumn = (Number(this.className.slice(1, 3)) % 7);
  //create an array to store all the slots that share the above column
  const columnArray = [];

  //grab all the slots that sit in that column
  for (let i = 0; i < board.length; i++) {
    if (board[i] % 7 === slotColumn) columnArray.push(board[i]);
  }

  //drop chip in the chosen column
  dropChip(columnArray);

  function dropChip(column) {
    //select bottom most slot that's available in the column
    for (let i = column.length - 1; i > 0; i--) {
      if (column[i] !== 'p1' || column[i] !== 'p2') {
        board[column[i]] = player;
        slots[column[i]].classList.add(player);
        switchPlayer(player);
        break;
      }
    }

    function switchPlayer(currentPlayer) {
      if (currentPlayer === 'p1') player = 'p2';
      else if (currentPlayer === 'p2') player = 'p1';
    }
    console.log(board);
  }
}
/** {
	outline: 1px solid red;
}*/

*,
*:before,
*:after {
  box-sizing: inherit;
}

html {
  box-sizing: border-box;
}

html,
body {
  margin: 0;
  padding: 0;
  background-color: #e5e6e8;
}

body {
  display: flex;
  justify-content: center;
  min-height: 100vh;
}

.board-wrapper {
  padding-top: 100px;
  display: flex;
  justify-content: center;
  margin: auto auto 0 auto;
  /*ask why this is needed*/
  position: relative;
}

.board {
  display: flex;
  flex-wrap: wrap;
  max-width: 706px;
  background-color: #00c;
  padding: 3px;
}

.board div {
  width: 100px;
  height: 100px;
  background-color: blue;
  border: 3px solid #00c;
  position: relative;
}

.board div:after {
  content: "";
  display: inline-block;
  width: 80px;
  height: 80px;
  border-radius: 50%;
  background-color: #00c;
  position: absolute;
  left: 0;
  top: 0;
  right: 0;
  bottom: 0;
  margin: auto;
  box-shadow: inset 0px 0px 13px #0606aa;
}

.board .chip {
  display: block;
  position: absolute;
  background-color: transparent;
  top: 0;
  left: 0;
  right: 0;
  height: 100px;
}

.board .chip:after {
  content: "";
  width: 80px;
  height: 80px;
  border-radius: 50%;
  background-color: red;
  position: absolute;
  left: 3px;
  top: 0;
  opacity: 0;
  transition: all .5s ease;
}

.board .chip:before {
  content: "";
  width: 50px;
  height: 50px;
  border-radius: 50%;
  background-color: red;
  position: absolute;
  left: 18px;
  top: 15px;
  z-index: 1;
  box-shadow: inset 0px 0px 20px #cc0000;
  opacity: 0;
  transition: all .5s ease;
}

.board div:nth-of-type(7n+1):hover~.chip:after {
  transform: translateX(10px);
  opacity: 1;
}

.board div:nth-of-type(7n+1):hover~.chip:before {
  transform: translateX(10px);
  opacity: 1;
}

.board div:nth-of-type(7n+2):hover~.chip:after {
  transform: translateX(110px);
  opacity: 1;
}

.board div:nth-of-type(7n+2):hover~.chip:before {
  transform: translateX(110px);
  opacity: 1;
}

.board div:nth-of-type(7n+3):hover~.chip:after {
  transform: translateX(210px);
  opacity: 1;
}

.board div:nth-of-type(7n+3):hover~.chip:before {
  transform: translateX(210px);
  opacity: 1;
}

.board div:nth-of-type(7n+4):hover~.chip:after {
  transform: translateX(310px);
  opacity: 1;
}

.board div:nth-of-type(7n+4):hover~.chip:before {
  transform: translateX(310px);
  opacity: 1;
}

.board div:nth-of-type(7n+5):hover~.chip:after {
  transform: translateX(410px);
  opacity: 1;
}

.board div:nth-of-type(7n+5):hover~.chip:before {
  transform: translateX(410px);
  opacity: 1;
}

.board div:nth-of-type(7n+6):hover~.chip:after {
  transform: translateX(510px);
  opacity: 1;
}

.board div:nth-of-type(7n+6):hover~.chip:before {
  transform: translateX(510px);
  opacity: 1;
}

.board div:nth-of-type(7n+7):hover~.chip:after {
  transform: translateX(610px);
  opacity: 1;
}

.board div:nth-of-type(7n+7):hover~.chip:before {
  transform: translateX(610px);
  opacity: 1;
}
<div class="board-wrapper">
  <div class="board">
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <span class="chip"></span>
  </div>
</div>

2 个答案:

答案 0 :(得分:3)

您需要克隆slot元素,否则它将从一个父对象移动到下一个父元素。

所以我添加了cloneNode()为每个位置创建一个新克隆。

//grab all slot positions on the board
const slots = document.querySelectorAll('.board div');
let player = 'p1';
let board = [
  0, 1, 2, 3, 4, 5, 6,
  7, 8, 9, 10, 11, 12, 13,
  14, 15, 16, 17, 18, 19, 20,
  21, 22, 23, 24, 25, 26, 27,
  28, 29, 30, 31, 32, 33, 34,
  35, 36, 37, 38, 39, 40, 41,
]

let slot = document.createElement('span');


//assign a class to each slot to represent its position
for (let i = 0; i < slots.length; i++) {
  //add class to each div
  slots[i].classList.add('c' + i);
  //add the slot to each div
  slots[i].appendChild(slot.cloneNode()); //<--------------------------- cloneNode()
  //add the function with the game logic to each slot
  slots[i].addEventListener('click', runGame);
}

function runGame() {
  //figure out which column the selected slot sits in
  const slotColumn = (Number(this.className.slice(1, 3)) % 7);
  //create an array to store all the slots that share the above column
  const columnArray = [];

  //grab all the slots that sit in that column
  for (let i = 0; i < board.length; i++) {
    if (board[i] % 7 === slotColumn) columnArray.push(board[i]);
  }

  //drop chip in the chosen column
  dropChip(columnArray);

  function dropChip(column) {
    //select bottom most slot that's available in the column
    for (let i = column.length - 1; i > 0; i--) {
      if (column[i] !== 'p1' || column[i] !== 'p2') {
        board[column[i]] = player;
        slots[column[i]].classList.add(player);
        switchPlayer(player);
        break;
      }
    }

    function switchPlayer(currentPlayer) {
      if (currentPlayer === 'p1') player = 'p2';
      else if (currentPlayer === 'p2') player = 'p1';
    }
    console.log(board);
  }
}
/** {
	outline: 1px solid red;
}*/

*,
*:before,
*:after {
  box-sizing: inherit;
}

html {
  box-sizing: border-box;
}

html,
body {
  margin: 0;
  padding: 0;
  background-color: #e5e6e8;
}

body {
  display: flex;
  justify-content: center;
  min-height: 100vh;
}

.board-wrapper {
  padding-top: 100px;
  display: flex;
  justify-content: center;
  margin: auto auto 0 auto;
  /*ask why this is needed*/
  position: relative;
}

.board {
  display: flex;
  flex-wrap: wrap;
  max-width: 706px;
  background-color: #00c;
  padding: 3px;
}

.board div {
  width: 100px;
  height: 100px;
  background-color: blue;
  border: 3px solid #00c;
  position: relative;
}

.board div:after {
  content: "";
  display: inline-block;
  width: 80px;
  height: 80px;
  border-radius: 50%;
  background-color: #00c;
  position: absolute;
  left: 0;
  top: 0;
  right: 0;
  bottom: 0;
  margin: auto;
  box-shadow: inset 0px 0px 13px #0606aa;
}

.board .chip {
  display: block;
  position: absolute;
  background-color: transparent;
  top: 0;
  left: 0;
  right: 0;
  height: 100px;
}

.board .chip:after {
  content: "";
  width: 80px;
  height: 80px;
  border-radius: 50%;
  background-color: red;
  position: absolute;
  left: 3px;
  top: 0;
  opacity: 0;
  transition: all .5s ease;
}

.board .chip:before {
  content: "";
  width: 50px;
  height: 50px;
  border-radius: 50%;
  background-color: red;
  position: absolute;
  left: 18px;
  top: 15px;
  z-index: 1;
  box-shadow: inset 0px 0px 20px #cc0000;
  opacity: 0;
  transition: all .5s ease;
}

.board div:nth-of-type(7n+1):hover~.chip:after {
  transform: translateX(10px);
  opacity: 1;
}

.board div:nth-of-type(7n+1):hover~.chip:before {
  transform: translateX(10px);
  opacity: 1;
}

.board div:nth-of-type(7n+2):hover~.chip:after {
  transform: translateX(110px);
  opacity: 1;
}

.board div:nth-of-type(7n+2):hover~.chip:before {
  transform: translateX(110px);
  opacity: 1;
}

.board div:nth-of-type(7n+3):hover~.chip:after {
  transform: translateX(210px);
  opacity: 1;
}

.board div:nth-of-type(7n+3):hover~.chip:before {
  transform: translateX(210px);
  opacity: 1;
}

.board div:nth-of-type(7n+4):hover~.chip:after {
  transform: translateX(310px);
  opacity: 1;
}

.board div:nth-of-type(7n+4):hover~.chip:before {
  transform: translateX(310px);
  opacity: 1;
}

.board div:nth-of-type(7n+5):hover~.chip:after {
  transform: translateX(410px);
  opacity: 1;
}

.board div:nth-of-type(7n+5):hover~.chip:before {
  transform: translateX(410px);
  opacity: 1;
}

.board div:nth-of-type(7n+6):hover~.chip:after {
  transform: translateX(510px);
  opacity: 1;
}

.board div:nth-of-type(7n+6):hover~.chip:before {
  transform: translateX(510px);
  opacity: 1;
}

.board div:nth-of-type(7n+7):hover~.chip:after {
  transform: translateX(610px);
  opacity: 1;
}

.board div:nth-of-type(7n+7):hover~.chip:before {
  transform: translateX(610px);
  opacity: 1;
}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Connect Four</title>
  <link rel="stylesheet" href="style.css">
</head>

<body>
  <div class="board-wrapper">
    <div class="board">
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <span class="chip"></span>
    </div>
  </div>
  <script src="script.js"></script>
</body>

</html>

我同意@Mohd Asim Suhail和@Towkir。您可以将slot的创建移入循环。没关系,您要做的就是创建插槽而不对其进行任何其他操作。但是,如果创建slot,然后添加类和子级,则使用cloneNode(true)的速度会更快。 (true也会克隆所有子级。)

鉴于您的示例的编写方式,我可能会将其更改为如下形式:

//grab all slot positions on the board
const COLUMNS = 7;
const ROWS = 7;
const boardEl = document.querySelector('.board');
let player = 1;
let board = [];
boardEl.addEventListener('click', runGame);

let c = 0;

// Set up the board, assign a class to each slot to represent its position
for (let row = 0; row < ROWS; row++) {
  const newRow = [];
  for (let col = 0; col < COLUMNS; col++) {
    newRow.push(0);
    slot = document.createElement('div');
    slot.classList.add('c' + c++);  //add class to each div
    slot.setAttribute('col', col);
    slot.setAttribute('row', row);
    slot.innerHTML = '<span></span>'; //add the slot to each div
    boardEl.appendChild(slot);
  }

  board.push(newRow);
}

const chip = document.createElement('span');
chip.className = 'chip';
boardEl.appendChild(chip);


function switchPlayer() {
  player = player === 1 ? 2 : 1;
}

function dropChip(col) {
  const colData = board[col];
  
  //select bottom most slot that's available in the column
  for (let i = ROWS-1; i >= 0; i--) {
    if (colData[i] === 0) {
      colData[i] = player;
      const el = boardEl.querySelector(`[col="${col}"][row="${i}"]`)
      el.classList.add(`p${player}`);
      break;
    }
  }

  switchPlayer(player);
}


function runGame(evt) {
  let slot = evt.target;
  // If they clicked on the `<span>` the move to the `<div>`
  if (slot.nodeName === 'SPAN') {
    slot = slot.parentElement;
  }

  //figure out which column the selected slot sits in
  const col = Number(slot.getAttribute('col'));

  //drop chip in the chosen column
  dropChip(col);
}
/** {
	outline: 1px solid red;
}*/

*,
*:before,
*:after {
  box-sizing: inherit;
}

html {
  box-sizing: border-box;
}

html,
body {
  margin: 0;
  padding: 0;
  background-color: #e5e6e8;
}

body {
  display: flex;
  justify-content: center;
  min-height: 100vh;
}

.board-wrapper {
  padding-top: 100px;
  display: flex;
  justify-content: center;
  margin: auto auto 0 auto;
  /*ask why this is needed*/
  position: relative;
}

.board {
  display: flex;
  flex-wrap: wrap;
  max-width: 706px;
  background-color: #00c;
  padding: 3px;
}

.board div {
  width: 100px;
  height: 100px;
  background-color: blue;
  border: 3px solid #00c;
  position: relative;
}

.board div:after {
  content: "";
  display: inline-block;
  width: 80px;
  height: 80px;
  border-radius: 50%;
  background-color: #00c;
  position: absolute;
  left: 0;
  top: 0;
  right: 0;
  bottom: 0;
  margin: auto;
  box-shadow: inset 0px 0px 13px #0606aa;
}

.board .chip {
  display: block;
  position: absolute;
  background-color: transparent;
  top: 0;
  left: 0;
  right: 0;
  height: 100px;
}

.board .chip:after {
  content: "";
  width: 80px;
  height: 80px;
  border-radius: 50%;
  background-color: red;
  position: absolute;
  left: 3px;
  top: 0;
  opacity: 0;
  transition: all .5s ease;
}

.board .chip:before {
  content: "";
  width: 50px;
  height: 50px;
  border-radius: 50%;
  background-color: red;
  position: absolute;
  left: 18px;
  top: 15px;
  z-index: 1;
  box-shadow: inset 0px 0px 20px #cc0000;
  opacity: 0;
  transition: all .5s ease;
}

.board div:nth-of-type(7n+1):hover~.chip:after {
  transform: translateX(10px);
  opacity: 1;
}

.board div:nth-of-type(7n+1):hover~.chip:before {
  transform: translateX(10px);
  opacity: 1;
}

.board div:nth-of-type(7n+2):hover~.chip:after {
  transform: translateX(110px);
  opacity: 1;
}

.board div:nth-of-type(7n+2):hover~.chip:before {
  transform: translateX(110px);
  opacity: 1;
}

.board div:nth-of-type(7n+3):hover~.chip:after {
  transform: translateX(210px);
  opacity: 1;
}

.board div:nth-of-type(7n+3):hover~.chip:before {
  transform: translateX(210px);
  opacity: 1;
}

.board div:nth-of-type(7n+4):hover~.chip:after {
  transform: translateX(310px);
  opacity: 1;
}

.board div:nth-of-type(7n+4):hover~.chip:before {
  transform: translateX(310px);
  opacity: 1;
}

.board div:nth-of-type(7n+5):hover~.chip:after {
  transform: translateX(410px);
  opacity: 1;
}

.board div:nth-of-type(7n+5):hover~.chip:before {
  transform: translateX(410px);
  opacity: 1;
}

.board div:nth-of-type(7n+6):hover~.chip:after {
  transform: translateX(510px);
  opacity: 1;
}

.board div:nth-of-type(7n+6):hover~.chip:before {
  transform: translateX(510px);
  opacity: 1;
}

.board div:nth-of-type(7n+7):hover~.chip:after {
  transform: translateX(610px);
  opacity: 1;
}

.board div:nth-of-type(7n+7):hover~.chip:before {
  transform: translateX(610px);
  opacity: 1;
}

.board span {
  border-radius: 50%;
  display: inline-block;
  height: 80px;
  left: 10px;
  position: relative;
  top: 10px;
  width: 80px;
  z-index: 999;
}
.board .p1 span {
  background-color: red;
}

.board .p2 span {
  background-color: black;
}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Connect Four</title>
  <link rel="stylesheet" href="style.css">
</head>

<body>
  <div class="board-wrapper">
    <div class="board">
    </div>
  </div>
  <script src="script.js"></script>
</body>

</html>

此版本的代码将您的电路板转换为二维数组,只需要一个事件处理程序就可以正常工作。

答案 1 :(得分:0)

您可以移动

let slot = document.createElement('span');

在for循环内的

行可以解决该问题。

请参阅此link,以进一步了解DOM中appendChild的行为。