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

首次打开Modal时出现卡顿的原因排查求助

Modal首次打开时卡顿的问题排查与修复

卡顿仅在Modal首次打开时出现。我原本推测原因是在body上绑定单个事件监听器且处理函数包含多条件判断(用于实现点击Modal外部关闭功能),但这个推测不成立。

相关代码如下:

open.addEventListener('click', (e) => {
    e.stopPropagation();
    change();

    document.body.addEventListener('click', takeInput);
});

function takeInput(e) {
    e.stopPropagation();
    let form = document.querySelector('.details_section');
    let formData = new FormData(form);
    if (e.target.closest('.shut') || (!e.target.closest('.modal'))) {
        form.reset();
        change();

    }

    else if (e.target.closest('.signin')) {
        if (form.checkValidity()) {
            console.log('true')
            change();
          form.reset();
        }
        else {
            console.log('false')
            form.reportValidity();

        }
    }
    else if (e.target.closest('.reset')) {
        form.reset();
    }

}

问题分析

  1. 重复绑定事件监听器:每次点击打开按钮,都会给body新增一个takeInput监听器,首次打开虽只绑一次,但后续重复打开会导致多个监听器叠加,触发时多次执行,积累性能问题。
  2. 重复DOM查询:每次触发takeInput都重新查询.details_section,首次打开时DOM刚渲染,查询开销更明显。
  3. 不必要的FormData创建:无论点击什么元素,都创建FormData,但只有登录分支才可能用到,浪费性能。
  4. 事件冒泡处理不当:在body监听器里调用e.stopPropagation(),会阻止其他事件正常冒泡,可能引发额外逻辑冲突。

修复方案

  1. 缓存DOM元素:提前获取并复用DOM节点,避免重复查询
  2. 避免重复绑定事件:初始化时只绑定一次body监听器,或在关闭Modal时移除监听器
  3. 优化事件冒泡逻辑:在Modal容器上绑定点击事件阻止冒泡,替代body监听器里的判断
  4. 按需创建FormData:仅在登录分支里创建FormData,减少不必要的开销

修改后的示例代码:

// 提前缓存DOM元素
const openBtn = document.querySelector('.open');
const form = document.querySelector('.details_section');
const modal = document.querySelector('.modal');

// 初始化时绑定一次body点击事件
document.body.addEventListener('click', handleModalOutsideClick);

// Modal内部点击阻止冒泡,避免触发外部关闭逻辑
modal.addEventListener('click', (e) => e.stopPropagation());

openBtn.addEventListener('click', (e) => {
  e.stopPropagation();
  toggleModal();
});

function handleModalOutsideClick(e) {
  if (e.target.closest('.shut') || !modal.contains(e.target)) {
    form.reset();
    toggleModal();
  } else if (e.target.closest('.signin')) {
    if (form.checkValidity()) {
      console.log('true');
      // 仅在此处创建FormData
      const formData = new FormData(form);
      toggleModal();
      form.reset();
    } else {
      console.log('false');
      form.reportValidity();
    }
  } else if (e.target.closest('.reset')) {
    form.reset();
  }
}

// 假设toggleModal是控制Modal显示/隐藏的函数
function toggleModal() {
  // 你的显示/隐藏逻辑
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 12:20:39