思路就是包含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));
}
}