如何用原生JavaScript+HTML高效实现10x10网格相邻方块变色功能?
Nice catch on the inefficiency here! Your current solution works, but we can streamline it significantly to be faster and cleaner. The main issues with your approach are repeated DOM queries (via querySelector) and redundant conditional blocks. Let's fix both with two key optimizations: storing cells in a 2D array for O(1) access, and using event delegation to reduce event listener overhead.
Step 1: Store Cells in a 2D Array
Instead of querying the DOM every time a cell is clicked, we'll build a 2D array when initializing the grid. This lets us directly access adjacent cells using row/column indices, which is way faster than traversing the DOM each time.
Step 2: Use Event Delegation
Instead of attaching a click listener to every single <td>, we'll attach one listener to the parent <table>. This reduces memory usage and makes initialization faster, especially for larger grids.
Full Optimized Code
HTML
<table id="grid"></table>
CSS
#grid { border-collapse: collapse; } #grid td { width: 30px; height: 30px; border: 1px solid #ddd; cursor: pointer; } .yellow { background-color: yellow; }
JavaScript
const grid = document.getElementById('grid'); const gridSize = 10; // 2D array to store all grid cells for quick access const gridCells = []; // Initialize the grid function buildGrid() { for (let row = 0; row < gridSize; row++) { const tableRow = document.createElement('tr'); const rowCells = []; for (let col = 0; col < gridSize; col++) { const cell = document.createElement('td'); // Store row/col in dataset for reference cell.dataset.row = row; cell.dataset.col = col; tableRow.appendChild(cell); rowCells.push(cell); } grid.appendChild(tableRow); gridCells.push(rowCells); } // Attach single click listener to the table grid.addEventListener('click', handleGridClick); } // Handle click events via delegation function handleGridClick(e) { // Ignore clicks that aren't on a cell if (e.target.tagName !== 'TD') return; const row = parseInt(e.target.dataset.row); const col = parseInt(e.target.dataset.col); // Define all four adjacent directions in a reusable array const directions = [ [-1, 0], // Up [1, 0], // Down [0, -1], // Left [0, 1] // Right ]; // Loop through directions instead of writing 4 separate if blocks directions.forEach(([rowOffset, colOffset]) => { const adjacentRow = row + rowOffset; const adjacentCol = col + colOffset; // Check if the adjacent cell is within grid bounds if (adjacentRow >= 0 && adjacentRow < gridSize && adjacentCol >= 0 && adjacentCol < gridSize) { gridCells[adjacentRow][adjacentCol].classList.toggle('yellow'); } }); } // Build the grid on page load buildGrid();
Why This Is Better
- Faster Cell Access: The 2D array lets us grab adjacent cells in constant time (
O(1)), no more slow DOM queries with complex selector strings. - Cleaner Logic: Using a directions array eliminates redundant
ifblocks—one loop handles all four adjacent cells. - Better Performance: Event delegation cuts down on the number of event listeners from 100 to 1, reducing memory usage and speeding up initialization.
- Easier Maintenance: If you ever want to add more directions (like diagonals), you just add a new entry to the
directionsarray instead of writing more conditional code.
内容的提问来源于stack exchange,提问作者Anon User

