Etch-a-Sketch项目性能优化求助:大网格下页面卡顿崩溃
Etch-a-Sketch 性能优化方案
你的代码主要存在重复事件绑定、O(n²)级别的DOM操作、低效的手动尺寸计算这几个核心性能问题,导致大网格下页面卡顿甚至崩溃。下面是针对性的优化方案:
核心优化点
- 用CSS Grid替代手动尺寸计算:直接通过CSS Grid定义网格行列,浏览器自动分配每个单元格的大小,完全省去JS遍历修改样式的步骤。
- 事件委托减少监听数量:不给每个单元格单独绑定
mouseover,而是把事件绑定到网格容器上,利用事件冒泡处理所有单元格的悬停事件,不管网格多大都只需要一个监听。 - 批量创建DOM元素:先把所有单元格创建好,一次性添加到容器,避免频繁触发页面重排。
- 修复输入验证逻辑:用循环替代递归,处理非数字输入,避免递归导致的栈溢出。
- 移除冗余操作:删除循环内重复定义的函数和重复的DOM查询,减少不必要的计算开销。
优化后的完整代码
const body = document.body; const bodyDiv = document.createElement('div'); bodyDiv.setAttribute('id', 'boxContainer'); body.append(bodyDiv); const btnDiv = document.createElement('div'); btnDiv.setAttribute('id', 'btnDiv'); bodyDiv.append(btnDiv); const btn = document.createElement('button'); btn.setAttribute('id', 'changeGridSizeBtn'); btn.innerText = 'Click to change grid size!'; btnDiv.append(btn); const gridContainer = document.createElement('div'); gridContainer.setAttribute('id', 'gridContainer'); // 初始化CSS Grid样式 gridContainer.style.display = 'grid'; gridContainer.style.width = '960px'; gridContainer.style.height = '720px'; gridContainer.style.gap = '2px'; // 替代原代码中box的间距 bodyDiv.append(gridContainer); // 随机颜色函数 function randomColor(){ let randomColorGenerator = Math.floor(Math.random()*16777215).toString(16); return '#' + randomColorGenerator; } // 事件委托:单次绑定处理所有单元格悬停 gridContainer.addEventListener('mouseover', (event) => { if (event.target.classList.contains('box')) { event.target.style.backgroundColor = randomColor(); } }); // 按钮悬停效果 btn.addEventListener('mouseenter', () => { btnDiv.style.boxShadow = '5px 10px #888888'; }); btn.addEventListener('mouseleave', () => { btnDiv.style.removeProperty('box-shadow'); }); // 初始化默认16x16网格 createGrid(16); // 复用的网格创建函数 function createGrid(size) { // 清空现有网格 gridContainer.innerHTML = ''; // 设置Grid行列布局 gridContainer.style.gridTemplateColumns = `repeat(${size}, 1fr)`; gridContainer.style.gridTemplateRows = `repeat(${size}, 1fr)`; // 批量创建单元格,用文档片段减少重排 const fragment = document.createDocumentFragment(); for (let i = 0; i < size * size; i++) { const boxDiv = document.createElement('div'); boxDiv.className = 'box'; boxDiv.style.backgroundColor = '#fff'; fragment.appendChild(boxDiv); } gridContainer.appendChild(fragment); } // 按钮点击处理逻辑 btn.addEventListener('click', () => { let userGridSize; // 循环验证输入,替代递归避免栈溢出 while (true) { userGridSize = prompt('Please enter a number between 1-100 for the grid size.'); if (userGridSize === null) break; // 处理用户取消输入 const num = parseInt(userGridSize); if (!isNaN(num) && num >=1 && num <=100) { createGrid(num); break; } else { alert('Invalid input! Please enter a number between 1 and 100.'); } } });
优化效果说明
- 网格尺寸超过40时不会再卡顿:CSS Grid的布局效率远高于手动JS计算,事件委托也避免了大量重复监听。
- 代码结构更清晰:把创建网格的逻辑封装成复用函数,减少冗余代码。
- 输入验证更健壮:处理了非数字、超出范围以及用户取消输入的情况。
内容的提问来源于stack exchange,提问作者benjamin1
相关产品推荐
相关产品推荐

