异步循环函数启停控制求助:鼠标在swiper周边运行、悬停时停止
Swiper自动hover效果的启停控制方案
需求说明
我正在做第一个项目,写了个异步函数,通过无限循环给swiper的每个元素逐个添加hover类。需要实现:鼠标在swiper周边区域时运行这个函数,鼠标悬停在swiper上时停止函数运行。
原代码
const delay = async (ms = 1000) => new Promise(resolve => setTimeout(resolve, ms)); async function swiping(exit) { for(let i=0; i < img.length; i++){ img[i].classList.add('imghover'); button[i].classList.add('btnhover'); console.log(i); await delay(3000); img[i].classList.remove('imghover'); button[i].classList.remove('btnhover'); await delay(400); if(i === 1 || i ===3 ){ swiper.slideNext(); await delay(300) } if(i === 3){ i = -1 } } }
解决方案
要实现这个需求,核心是给异步循环加一个可控制的中断标志,再结合鼠标事件切换标志状态来启停函数。
1. 新增控制变量
先定义两个变量,用来跟踪函数运行状态和保存异步任务引用:
// 控制循环是否继续的开关 let isRunning = false; // 保存异步函数实例,方便后续管理 let swipingTask = null;
2. 修改原异步函数
把原for循环改成while循环,加入标志位检查,确保能及时响应中断:
const delay = async (ms = 1000) => new Promise(resolve => setTimeout(resolve, ms)); async function swiping() { isRunning = true; let i = 0; // 用while循环替代for,更灵活控制启停 while (isRunning) { img[i].classList.add('imghover'); button[i].classList.add('btnhover'); console.log(i); await delay(3000); // 每次等待后都检查开关,避免卡死在等待中 if (!isRunning) break; img[i].classList.remove('imghover'); button[i].classList.remove('btnhover'); await delay(400); if (!isRunning) break; if(i === 1 || i ===3 ){ swiper.slideNext(); await delay(300); if (!isRunning) break; } // 简化索引循环逻辑,替代原i=-1的写法 i = (i + 1) % 4; } isRunning = false; }
3. 添加鼠标事件监听
假设你的swiper容器选择器是.swiper,周边区域是包裹它的父元素(比如.swiper-surround),给这两个元素加鼠标事件:
const swiperEl = document.querySelector('.swiper'); const surroundEl = document.querySelector('.swiper-surround'); // 替换成你的周边区域选择器 // 鼠标进入周边区域,启动函数(如果没在运行) surroundEl.addEventListener('mouseenter', () => { if (!isRunning) { swipingTask = swiping(); } }); // 鼠标离开周边区域,停止函数 surroundEl.addEventListener('mouseleave', () => { isRunning = false; }); // 鼠标进入swiper本身,停止函数 swiperEl.addEventListener('mouseenter', () => { isRunning = false; }); // 鼠标离开swiper回到周边区域,重新启动函数 swiperEl.addEventListener('mouseleave', () => { if (!isRunning) { swipingTask = swiping(); } });
关键说明
- 每个
await后都加isRunning检查,确保即使在等待过程中触发停止,函数也能及时中断 - 用
(i + 1) % 4简化了原索引重置逻辑,效果和原代码i到3后设为-1完全一致,但更易读 - 通过
isRunning标志位控制循环,避免了强制终止异步任务可能带来的内存泄漏问题
内容的提问来源于stack exchange,提问作者Mateusz Małolepszy
相关产品推荐
相关产品推荐

