使用javascript冒泡/捕获检测中间节点

时间:2017-05-02 17:02:43

标签: javascript addeventlistener event-bubbling event-capturing

我需要使用事件委派来捕获带有图像的锚节点。

document.addEventListener(
  'click',
  function(event) {
    console.log(event.target);
    return true;
  },
  false
);
<a href="#" class="link">
  <img src="http://placehold.it/100x100" alt="">
</a>

event.target 始终为 img

如何检查是否在具有类.link?

的节点上进行了单击

更新:要明确an example with jQuery

当我使用jQuery.on()时,回调函数中的a属性中有this个节点,而不是img节点。使用纯JS我只能确定初始目标。

2 个答案:

答案 0 :(得分:1)

您可以通过调用

来检查元素是否具有类
element.classList.contains('link');

您现在想要的是在点击<img>内的<a class="link">时执行某些操作。要确定点击的<img>是否有父<a class="link">,我们必须遍历其父树并进行检查。

这与您拥有的jQuery示例非常相似,即

$('body').on('click', '.link', callback)

除了jQuery匹配整个查询,而不仅仅是一个类。

以下是你如何做到这一点:

// function to determine if the element has the link class
const hasLinkClass = element => element
  ? element.classList && element.classList.contains('link')
  : false;

// function that accepts an event handler and returns
// a wrapper function arround it.
// The wrapper is called it if the passed in event 
// object contains as its target an <img> with a parent
// with .link class
function filterImagesWithinLinks(handler) {
  return function(event) {
    let elem = event.target;

    // ignore clicks that are not on an image (it might be better to be more specific here)
    if (elem.tagName === 'IMG') {
    
      // filter until we find the parent with .link class
      while (elem && !hasLinkClass(elem)) {
        elem = elem.parentNode;
      }

      // if a parent with .link class was found, 
      // call the original handler and set its `this`
      // to the parent.
      if (elem) {
        handler.call(elem, event);
      }
    }
  };
}

// function handler that fires when 
// an <img> that has a parent with 
// class 'link' was clicked
function handler(event) {
  console.log('target : ', event.target);
  console.log('this   : ', this);
}

document.addEventListener(
  'click',
  filterImagesWithinLinks(handler),
  false
);
a.link {
  display: block;
  padding: 10px;
  background: #018bbc;
}

.middle {
  background: salmon;
  padding: 10px;
  text-align: center;
}
<a href="#" class="link">
  <p class="middle">
    <img src="http://placehold.it/100x100" alt="" />
  </p>
</a>

答案 1 :(得分:0)

如果您向锚标记添加一些文字或其他内容,则会更容易看到aimg之间的差异。在JSFiddle上查看此示例 - 它显示是否单击了类link的元素:

<强> https://jsfiddle.net/Lppt4hyk/4/

这里是代码(只是稍微修改过你的代码):

<a href="#" class="link"> Anchor
  <img src="http://placehold.it/100x100" alt="">
</a>
document.addEventListener(
  'click',
    function( event ) {
            var patt = /(?:^link | link$|^link$| link )/g;
            if (patt.test(event.target.className)) {
        alert('link class was clicked');
      }
      else { alert('link class was not clicked'); }
    return true;
  },
    false
);
div {
  background: red;
  display: block;
  height: 90%;
  width: 90%;
}

.n1 {
    background: yellow;
}

.n2 {
    background: green;
}

更新:如果link类名不是分配给该元素的唯一类,则添加了对link类名称的检查。

更新:添加正则表达式检查以清除{{1}}作为更大词的一部分。