You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

页面多JS Swiper实例销毁问题:桌面端销毁时实例数组为空的解决方法

问题分析与解决方案

嘿,我一眼就看到问题出在哪了——你把存储Swiper实例的swiperArray和init变量放在了swiperMode函数的内部!这意味着每次调用swiperMode(不管是页面加载还是窗口 resize),都会重新创建一个空的swiperArray,之前在移动端创建的实例根本没法被后续的销毁逻辑访问到。

核心问题拆解

当窗口尺寸是移动端时,你创建了Swiper实例并存在局部的swiperArray里,但函数执行完毕后,这个局部数组就被垃圾回收了。等你把窗口拉大到桌面宽度,再次调用swiperMode时,新的swiperArray是空的,自然销毁逻辑直接返回,没法清理之前的实例。

修复方案

把swiperArray和init变量移到函数外部,让它们在全局(或者至少是函数作用域之外)保持持久化。另外,我还优化了窗口宽度的判断方式,以及添加了防抖逻辑避免resize频繁触发:

// 把变量移到函数外部,保持持久化
var init = false;
let swiperArray = [];

function swiperMode() {
  const mobileBreakpoint = 972;
  let allWorks = document.querySelectorAll('.work-item__images');
  
  const buildSlider = (element) => {
    return new Swiper(element, {
      loop: true,
      observer: true,
      observeParents: true,
      slidesPerView: 2.5,
      spaceBetween: 16,
    });
  }

  // 移动端初始化逻辑
  if (window.innerWidth <= mobileBreakpoint) {
    if (!init) {
      init = true;
      allWorks.forEach((item, id) => {
        const slider = buildSlider(item);
        swiperArray[id] = slider;
      });
    }
  } 
  // 桌面端销毁逻辑
  else {
    if (swiperArray.length === 0) return;
    
    // 遍历销毁每个实例,同时清理数组
    swiperArray.forEach(slider => {
      if (slider && typeof slider.destroy === 'function') {
        slider.destroy(true, true);
      }
    });
    swiperArray = [];
    init = false;
  }
}

// 防抖函数,避免resize频繁触发
function debounce(func, delay = 200) {
  let timeoutId;
  return (...args) => {
    clearTimeout(timeoutId);
    timeoutId = setTimeout(() => func.apply(this, args), delay);
  };
}

/* On Load **************************************************************/
window.addEventListener('load', swiperMode);
/* On Resize **************************************************************/
window.addEventListener('resize', debounce(swiperMode));

关键改动说明

  1. 变量持久化:swiperArray和init移到函数外部,确保每次调用swiperMode都能访问到同一个数组,保存之前创建的实例。
  2. 窗口宽度判断优化:用window.innerWidth替代document.body.clientWidth,前者更准确反映当前视口宽度,不受body的padding、margin样式影响。
  3. 安全销毁:在销毁前检查实例是否存在以及destroy方法是否可用,避免报错。
  4. 防抖resize:添加防抖函数,避免窗口调整时连续触发多次swiperMode,提升性能。

额外注意事项

  • 如果你的项目使用模块化开发(比如ES6模块),不要用全局变量,可以把swiperArray和init放在模块级作用域里,同样能保持持久化。
  • 确保allWorks每次调用swiperMode都重新获取,避免DOM结构变化后实例找不到对应的元素。

内容的提问来源于stack exchange,提问作者Masha Baranova

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.27 18:34:06