关闭弹窗小思路!!!!你不会可太out了
评论
收藏

关闭弹窗小思路!!!!你不会可太out了

经验分享
再见史蒂夫周
2025-11-10 13:00·浏览量:604
再见史蒂夫周
发布于 2025-11-10 13:00604浏览

思路就是包含icon-close的元素都点下 同意

(//*[@*[contains(., 'icon-close')]])[last()]|

可以适应这个关闭所有的属性带icon-close的元素,拼多多和淘宝都是试用的,其他未测试

可以封装为指令

下面是js快速点击的方法

function (element, input) {
  // 仅在 DOM 就绪后执行
  if (document.readyState !== 'loading') {
    clickIconClose();
  } else {
    document.addEventListener('DOMContentLoaded', clickIconClose, { once: true });
  }

  function clickIconClose() {
    // 任一属性值包含 "icon-close" 的元素
    const xpath = "//*[@*[contains(., 'icon-close')]]";
    const result = document.evaluate(
      xpath,
      document,
      null,
      XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
      null
    );

    const clicked = new Set(); // 防止重复点击同一节点
    const errors = [];           // 收集失败原因

    // 从后往前遍历,避免删除/修改集合导致漏项
    for (let i = result.snapshotLength - 1; i >= 0; i--) {
      const el = result.snapshotItem(i);
      if (!el || !el.isConnected || clicked.has(el)) continue;

      // 可见性快速判断(避免隐藏元素占用点击)
      const style = window.getComputedStyle(el);
      if (style.display === 'none' || style.visibility === 'hidden' || style.opacity === '0') {
        continue;
      }

      // 可交互性校验
      if (el.disabled || el.getAttribute('aria-disabled') === 'true') {
        continue;
      }

      // 被 pointer-events 禁用
      if (window.getComputedStyle(el).pointerEvents === 'none') {
        continue;
      }

      // 被其他元素遮挡(仅检查第一个遮挡者,提升性能)
      if (isCovered(el)) {
        continue;
      }

      // 尝试多种触发方式,优先原生 click,其次 dispatchEvent
      try {
        if (typeof el.click === 'function') {
          el.click();
          clicked.add(el);
          continue;
        }

        // 降级:派发合成事件(部分 SPA 只监听合成事件)
        const evt = new MouseEvent('click', {
          bubbles: true,
          cancelable: true,
          view: window,
          composed: true
        });
        if (el.dispatchEvent(evt)) {
          clicked.add(el);
        } else {
          errors.push({ el, reason: 'dispatchEvent 被阻止' });
        }
      } catch (e) {
        errors.push({ el, reason: e.message });
      }
    }

    // 可选:在控制台输出失败项,便于排查
    // console.warn('批量点击未成功项:', errors);
    return null;
  }

  // 判断元素是否被上层元素遮挡(简化版:检查视口矩形是否有有效交集)
  function isCovered(el) {
    const r = el.getBoundingClientRect();
    if (r.width === 0 || r.height === 0) return true;

    // 检查 el 是否被父级 clip-path/overflow 裁剪(简化:只看祖先 overflow)
    let parent = el.parentElement;
    while (parent && parent !== document.documentElement) {
      const pStyle = window.getComputedStyle(parent);
      if (pStyle.overflow === 'hidden' || pStyle.overflow === 'clip') {
        const pRect = parent.getBoundingClientRect();
        if (r.right < pRect.left || r.left > pRect.right || r.bottom < pRect.top || r.top > pRect.bottom) {
          return true;
        }
      }
      // 遇到 fixed 容器停止向上(常见遮罩层场景)
      if (pStyle.position === 'fixed') break;
      parent = parent.parentElement;
    }

    // 检查是否有其他可见元素覆盖在 el 中心点
    const cx = r.left + r.width / 2;
    const cy = r.top + r.height / 2;
    const topEls = document.elementsFromPoint(cx, cy);
    // 若最上层不是 el 自身,或其祖先,则认为被遮挡
    return !topEls.some(x => x === el || el.contains(x));
  }
}



收藏14
全部评论1
最新
发布评论
评论