element.matches(selector)用于判断当前元素是否匹配指定css选择器,返回布尔值;它仅检查该元素自身,不递归子元素,不支持伪元素和动态伪类,需确保选择器合法且注意浏览器兼容性。

element.matches 用法和基本判断逻辑
直接用 element.matches(selector) 就能判断当前节点是否匹配某个 CSS 选择器,返回布尔值。它不递归检查子元素,只看调用它的那个节点本身是否满足条件。
常见错误是传入无效选择器(比如空字符串、含语法错误的字符串),此时会抛出 SyntaxError;还有人误以为它支持伪元素(如 ::before),其实不支持——浏览器根本不允许伪元素被 JS 选中。
- 必须确保
selector是合法的、可被 CSS 引擎解析的选择器(如"button[data-action='submit']"、".card .title") - 不支持动态伪类以外的伪元素,
":hover"这类运行时状态也不参与匹配(只看静态结构) - 注意兼容性:IE 不支持,需用
element.msMatchesSelector回退(仅 IE8–10),现代项目通常忽略 IE
在事件监听中正确获取点击目标并匹配
很多人直接对 event.target 调用 matches,但没考虑事件冒泡路径上可能有多个符合条件的祖先节点。如果你只想知道“点击是否落在某类按钮上”,用 target 没问题;但若想捕获“点击是否发生在某个容器内的任意可操作子项”,就得配合 closest 或遍历父级。
示例场景:点击卡片区域,只要点中了带 data-role="delete" 的任意子元素,就触发删除逻辑。
document.addEventListener('click', (e) => {
if (e.target.matches('[data-role="delete"]')) {
handleDelete(e.target);
}
});
- 用
e.target最直接,但只匹配**精确点击的那个节点** - 如果想放宽到“点击区域包含该选择器的任意祖先”,改用
e.target.closest('[data-role="delete"]') - 避免在循环中反复调用
matches判断多个 selector,可用单次closest+ 切换判断逻辑更高效
与 querySelectorAll + Array.find 对比:什么时候不该用 matches
matches 是单节点判断,不是查找工具。有人试图用它替代 querySelectorAll 做批量筛选,结果写了一堆循环加判断,性能反而更差。
例如:你想找出页面里所有已激活的 tab 按钮,并高亮它们的父容器。这时候不该遍历所有 button 然后逐个 matches(".tab.active"),而应:
document.querySelectorAll('.tab.active').forEach(tab => {
tab.parentElement.classList.add('highlight');
});
-
matches适合“这个节点是不是我要的?”这种二元判断 -
querySelectorAll适合“哪些节点符合这个条件?”这种批量查找 - 若 selector 复杂且需复用(如正则式动态拼接),先缓存
new CSSStyleSheet()不现实,老实用字符串拼接 +matches,但注意 XSS 风险(别把用户输入直接当 selector)
容易忽略的细节::scope 和相对选择器行为
标准 DOM 中 matches 不支持 :scope(部分浏览器实验性支持但不可靠)。也就是说,你不能写 el.matches(':scope > .child') 来表达“是否为 el 的直系子元素”,它会被当作无效选择器报错。
真正需要这种语义时,得手动判断层级关系:
const isDirectChild = (el, parent) => el.parentNode === parent && parent.contains(el);
-
matches所有选择器都以当前节点为根进行匹配,不模拟“从该节点出发”的相对查找逻辑 -
">"、"+"、"~"这些组合器在matches中依然有效,但作用对象是当前节点自身,不是它和兄弟/父子的关系 - 比如
div.matches('div > span')永远是false,因为一个div不可能同时是div又是span
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











