事件冒泡与查询选择器

Event bubbling with querySelector

本文关键字:查询 选择器 事件      更新时间:2023-09-26

我有一个附加到容器的事件侦听器,我想过滤正在点击的内容。

在下面的示例中,我过滤掉了UL.head点击。

<div>
 <ul class="head">
  <li data-test="...">1</li>
  <li>2</li>
  <li>3</li>
 </ul>
 <ul class="head">
  <li>1</li>
  <li>2</li>
  <li data-test="...">3</li>
 </ul>
 <ul class="head">
  <li>1</li>
  <li data-test="...">2</li>
  <li>3</li>
 </ul>
</div>
document.querySelector('div').addEventListener('click', function(e) {
  var ul = findParentByClass(e.target, ".head");
  if(ul) { // clicke a UL }
});
function findParentByClass(node, cls) {
    while (node && !hasClass(node, cls)) {
        node = node.parentNode;
    }
    return node;
}

我想重现与findParentByClass类似的功能,但它会findParentByQuerySelector.所以我可以做这样的事情:

li = findParentByQuerySelector('li:[data-test]');
if(li) { // clicked li with data-test attribute }

我很困惑如何在这个冒泡的事件中实施querySelector

您可以简单地使用 Element.matches 方法:

function findParentBySelector(node, selector) {
    while (node && !node.matches(selector)) {
        node = node.parentNode;
    }
    return node;
}

但是,请注意,不幸的是,此方法的实现不一致。

或者,您可以使用更常见的Element.querySelectorAll,它与指定元素的子元素匹配。这确实意味着您需要考虑祖父母和父母:

function findParentBySelector(node, selector) {
    while (node && node.parentNode) {
        let list = node.parentNode.querySelectorAll(selector);
        if (Array.prototype.includes.call(list, node)) {
          return node
        }
        node = node.parentNode;
    }
    return node;
}

但我不会完全称这种方法漂亮。