手动可调整大小的弹出窗口性能不佳问题求助
手动调整侧边栏大小的性能优化方案
核心优化点及代码修改
1. 移除拖动时的CSS过渡动画
.sidenav的transition属性会在拖动过程中触发平滑过渡,导致视觉上的延迟感。我们可以在拖动时临时禁用过渡,结束后再恢复:
CSS修改:
.sidenav { /* 保留原有属性,新增以下配置 */ will-change: width; /* 提示浏览器提前优化width变化的渲染逻辑 */ } .sidenav.resizing { transition: none !important; /* 拖动时强制禁用过渡 */ } body.resizing { user-select: none; /* 拖动时禁止页面文本被选中,避免干扰操作 */ }
JavaScript关联修改:
在拖动开始/结束时,给对应元素添加/移除resizing类:
// 拖动开始 resizeButtonEl.addEventListener('mousedown', function(event) { // ... 原有代码 sidenavEl.classList.add('resizing'); bodyEl.classList.add('resizing'); }); // 拖动结束 function stopResizing() { // ... 原有代码 sidenavEl.classList.remove('resizing'); bodyEl.classList.remove('resizing'); }
2. 缓存DOM元素,减少重复查询
避免每次操作都重复调用getElementById,提前缓存常用DOM元素,降低DOM查询开销:
// 全局缓存常用元素 const sidenavEl = document.getElementById("mySidenav"); const resizeButtonEl = document.getElementById("resizeButton"); const overlayEl = document.getElementById("overlay"); const bodyEl = document.body; // 后续代码直接使用缓存变量,例如: function openNav() { sidenavEl.style.width = "500px"; overlayEl.style.display = "block"; bodyEl.style.backgroundColor = "rgba(0,0,0,0.1)"; }
3. 用requestAnimationFrame优化重绘时机
直接在mousemove回调中修改样式会频繁触发浏览器重排,使用requestAnimationFrame将样式修改放到浏览器的重绘周期内执行,减少不必要的渲染开销:
function resize(event) { if (isResizing) { const newWidth = startWidth - (event.clientX - startX); if (newWidth > 100) { requestAnimationFrame(() => { sidenavEl.style.width = `${newWidth}px`; }); } } }
4. 完善事件监听与边界处理
添加mouseleave事件监听,防止鼠标移出浏览器窗口后无法停止拖动;同时在mousedown时阻止默认行为,避免选中文本等干扰操作:
function stopResizing() { if (isResizing) { isResizing = false; sidenavEl.classList.remove('resizing'); bodyEl.classList.remove('resizing'); resizeButtonEl.style.cursor = "grab"; // 清理所有相关事件监听 document.removeEventListener('mousemove', resize); document.removeEventListener('mouseup', stopResizing); document.removeEventListener('mouseleave', stopResizing); } } // 绑定停止拖动的事件 document.addEventListener('mouseup', stopResizing); document.addEventListener('mouseleave', stopResizing); // mousedown时阻止默认行为 resizeButtonEl.addEventListener('mousedown', function(event) { event.preventDefault(); // 阻止文本选择等默认行为 // ... 原有初始化逻辑 });
完整优化后的JavaScript示例
const sidenavEl = document.getElementById("mySidenav"); const resizeButtonEl = document.getElementById("resizeButton"); const overlayEl = document.getElementById("overlay"); const bodyEl = document.body; let isResizing = false; let startX = 0; let startWidth = 0; function openNav() { sidenavEl.style.width = "500px"; overlayEl.style.display = "block"; bodyEl.style.backgroundColor = "rgba(0,0,0,0.1)"; } function closeNav() { sidenavEl.style.width = "0"; overlayEl.style.display = "none"; bodyEl.style.backgroundColor = "white"; } function resize(event) { if (isResizing) { const newWidth = startWidth - (event.clientX - startX); if (newWidth > 100) { requestAnimationFrame(() => { sidenavEl.style.width = `${newWidth}px`; }); } } } function stopResizing() { if (isResizing) { isResizing = false; sidenavEl.classList.remove('resizing'); bodyEl.classList.remove('resizing'); resizeButtonEl.style.cursor = "grab"; document.removeEventListener('mousemove', resize); document.removeEventListener('mouseup', stopResizing); document.removeEventListener('mouseleave', stopResizing); } } resizeButtonEl.addEventListener('mousedown', function(event) { event.preventDefault(); isResizing = true; startX = event.clientX; startWidth = parseFloat(getComputedStyle(sidenavEl).width); sidenavEl.classList.add('resizing'); bodyEl.classList.add('resizing'); resizeButtonEl.style.cursor = "grabbing"; document.addEventListener('mousemove', resize); document.addEventListener('mouseup', stopResizing); document.addEventListener('mouseleave', stopResizing); });
内容的提问来源于stack exchange,提问作者Jakub97
相关产品推荐
相关产品推荐

