【问题标题】:Click event listener is being repeatedly triggered without any clicks?点击事件监听器被重复触发而没有任何点击?
【发布时间】:2021-02-27 22:41:50
【问题描述】:

我正在开发一个“战舰”游戏,其中包含两个由 div 组成的网格,目前正在尝试为所有 div 添加一个点击事件侦听器。

我遇到的问题是,当我刷新页面时,事件监听器被反复触发(直到每个 div 都被点击),我不明白为什么......

这里是有问题的事件监听器:

 let aiGridCells = document.querySelectorAll(".ai-grid__game-cell");
 aiGridCells.forEach(cell => {
    cell.addEventListener("click", humanPlayer.humanAttack(cell.getAttribute('data-ai'),aiPlayer))
 });

其中 humanPlayer 是由工厂函数生成的对象:

const humanPlayer = playerFactory('human');
import gameboardFactory from './gameboardFactory';

const playerFactory = (name) => {

    const playerBoard = gameboardFactory();

    const humanAttack = (cell, player) => {   // Where player is opponent
        if (player.playerBoard.gameBoard[cell].id !== 'miss') {
            player.playerBoard.receiveAttack(cell);
        };
    };

    const aiAttack = (player) => {   // Where player is opponent
        const availableCells = [];
        for (let i = 0; i < player.playerBoard.gameBoard.length; i++) {
            if (player.playerBoard.gameBoard[i].id === null) {
                availableCells.push(i);
            };
        };
        const attackCell = Math.floor(Math.random() * availableCells.length); 
        player.playerBoard.receiveAttack(attackCell);
    };

    return {
        name,
        playerBoard,
        humanAttack,
        aiAttack
    }

};

export default playerFactory;

gameboardFactory 是:

import shipFactory from './shipFactory';

const gameboardFactory = () => {
    const gameBoard = [];
    const shipYard = [];

    const init = () => {
        for (let i = 0; i<100; i++) {
            gameBoard.push({id: null})
        };
    };

    const checkValidCoordinates = (direction, start, end) => {
        if (direction === 'horizontal') {
            if ((start <= 9) && (end <= 9)) {
                return true;
            } else {
                let newStart = (start/10).toString(10);
                let newEnd = (end/10).toString(10);
                if ((newStart.charAt(0)) === (newEnd.charAt(0))) {
                    return true;
                };
            };
        } else {
            if ((start <= 9) && (end <= 9)) {
                return false
            } else if (start <= 9) {
                let newStart = start.toString(10);
                let newEnd = end.toString(10);
                if ((newStart.charAt(0)) === (newEnd.charAt(1))) {
                    return true;
                };
            } else {
                let newStart = start.toString(10);
                let newEnd = end.toString(10);
                if ((newStart.charAt(1)) === (newEnd.charAt(1))) {
                    return true;
                };
            };
        };
        return false
    };

    const checkIfShipPresent = (direction, start, end) => {
        if (direction === 'horizontal') {
            for (let i = start; i <= end; i++) {
                if (gameBoard[i].id !== null) {
                    return true;
                }
            };
            return false;
        } else {
            for (let i = start; i <= end; i += 10) {
                if (gameBoard[i].id !== null) {
                    return true;
                }
            };
            return false;
        };
    };

    const placeShip = (id, direction, start, end) => {

        if (!checkValidCoordinates(direction, start, end)) {
            return;
        };

        if (checkIfShipPresent(direction, start, end)) {
            return;
        };
        
        const newShip = [];

        if (direction === 'horizontal') {
            for (let i = start; i <= end; i++) {
                gameBoard[i].id = id;
                newShip.push(i);
            };
        } else {
            for (let i = start; i <= end; i += 10) {
                gameBoard[i].id = id;
                newShip.push(i);  
            };
        };
        
        shipYard.push(shipFactory(id, newShip));
    };

    const receiveAttack = (cell) => {

        console.log(cell)
       
        if (gameBoard[cell].id !== null) {
            const attackedShip = shipYard.filter((ship) => {
                return ship.id === gameBoard[cell].id;
            })[0];
            if (!attackedShip.hits.includes(cell)) {
                attackedShip.hits.push(cell);
            };
        } else {
            gameBoard[cell].id = 'miss';
        };
    };

    const checkIfAllShipsSunk = () => {
        let allShipsSunk = true;
        shipYard.forEach((ship) => {
            if (ship.isSunk() === false) {
                allShipsSunk = false;
            };
        });
        return allShipsSunk;
    };

    if (gameBoard.length === 0) {
        init();
    };

    return { 
        gameBoard,
        placeShip,
        receiveAttack,
        shipYard,
        checkIfAllShipsSunk
    };
};

export default gameboardFactory;

我完全不知道问题可能是什么,并尝试了无数方法来纠正它。任何建议将不胜感激。

谢谢!

【问题讨论】:

    标签: javascript


    【解决方案1】:

    您试图在此处添加实际的函数调用作为侦听器:

     let aiGridCells = document.querySelectorAll(".ai-grid__game-cell");
     aiGridCells.forEach(cell => {
        cell.addEventListener("click", humanPlayer.humanAttack(cell.getAttribute('data-ai'),aiPlayer))
     });
    

    因此,在您的事件监听器初始化时,您实际上调用了您的函数,而不是将其作为监听器传递。

    你可以这样传递它:

     aiGridCells.forEach(cell => {
        cell.addEventListener("click",  () => humanPlayer.humanAttack(cell.getAttribute('data-ai'),aiPlayer))
     });
    

    【讨论】:

      猜你喜欢
      • 2020-03-19
      • 1970-01-01
      • 2012-06-13
      • 1970-01-01
      • 2013-03-10
      • 1970-01-01
      • 2012-11-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多