屏幕尺寸变化时无法正确重写全屏滑块的位置数组问题
全屏滑块窗口 resize 后定位异常问题
我正在做一个全屏滑块,正常使用没问题,但调整屏幕尺寸后就出问题了。我试着在 resize 事件里更新定位函数,但没法正确重写 screenPosition 数组。
原实现代码
const container = document.querySelector(".grid-container"); const screens = document.querySelectorAll("#screen"); const screensList = Array.from(screens); let screenWidth = 0; // MAYBE ABLE TO USE INSTEAD OF getBoundingClientRect().width // const observer = new ResizeObserver((entries) => { // console.log(entries[0].contentRect.width); // }); // observer.observe(screensList[0]); let screenPosition = []; const setScreenPosition = (screenWidth, currentScreen) => { screenPosition.push(screenWidth * currentScreen); }; const setScreenPositionOnResize = (currentScreen) => { screenPosition = []; setScreenPosition(screenWidth, currentScreen); }; const setScreenWidth = () => { return (screenWidth = screensList[0].getBoundingClientRect().width); }; setScreenWidth(); window.addEventListener("resize", () => { setScreenWidth(); }); screensList.forEach((scn, i) => { const nextBtn = scn.querySelector("#next"); const backBtn = scn.querySelector("#back"); const currentScreen = i + 1; setScreenPosition(screenWidth, currentScreen); window.addEventListener("resize", () => { setScreenPositionOnResize(currentScreen); }); const moveFwd = screenPosition[i]; const moveBk = screenPosition[i - 1] - screenWidth; if (nextBtn) { nextBtn.addEventListener("click", function () { container.style.transform = `translateX(-${moveFwd}px)`; }); } if (backBtn) { backBtn.addEventListener("click", function () { container.style.transform = "translateX(-" + moveBk + "px)"; }); } });
我尝试的重写数组代码
const setScreenPositionOnResize = (currentScreen) => { screenPosition = []; setScreenPosition(screenWidth, currentScreen); };
该函数在addEventListener("resize", ...)中被调用。
问题分析与修复方案
核心问题
- 重复绑定 resize 事件:在
screensList.forEach循环里,每个屏幕元素都绑定了一次 resize 事件,窗口 resize 时会触发多次setScreenPositionOnResize,每次都会清空数组再添加单个元素,最终数组只会保留最后一个屏幕的定位值。 - 定位值缓存未更新:
moveFwd和moveBk是初始化时获取的固定值,resize 后即使更新了screenPosition,点击事件仍使用旧值,不会同步新定位。
修复步骤
- 统一处理 resize 事件:将 resize 绑定移到循环外,避免重复触发,同时在宽度更新后重新计算所有屏幕的定位。
- 点击时动态获取定位:不在初始化时缓存定位值,而是在点击事件内根据最新的屏幕宽度和索引计算目标位置。
修复后的代码
const container = document.querySelector(".grid-container"); const screens = document.querySelectorAll("#screen"); const screensList = Array.from(screens); let screenWidth = 0; let screenPosition = []; // 计算所有屏幕的定位数组 const calculateAllScreenPositions = () => { screenPosition = []; screensList.forEach((_, i) => { screenPosition.push(screenWidth * (i + 1)); }); }; const setScreenWidth = () => { screenWidth = screensList[0].getBoundingClientRect().width; calculateAllScreenPositions(); }; // 初始化 setScreenWidth(); // 统一绑定resize事件 window.addEventListener("resize", setScreenWidth); screensList.forEach((scn, i) => { const nextBtn = scn.querySelector("#next"); const backBtn = scn.querySelector("#back"); if (nextBtn) { nextBtn.addEventListener("click", function () { const moveFwd = screenPosition[i]; container.style.transform = `translateX(-${moveFwd}px)`; }); } if (backBtn) { backBtn.addEventListener("click", function () { // 第一个屏幕回退时定位到0位置 const moveBk = screenPosition[i - 1] || 0; container.style.transform = `translateX(-${moveBk}px)`; }); } });
额外优化建议
可以用 ResizeObserver 替代 resize 事件,更精准监听容器宽度变化,避免频繁触发:
const observer = new ResizeObserver((entries) => { screenWidth = entries[0].contentRect.width; calculateAllScreenPositions(); }); observer.observe(screensList[0]);
内容的提问来源于stack exchange,提问作者Gdr
相关产品推荐
相关产品推荐

