【问题标题】:SVG elements eventsSVG 元素事件
【发布时间】:2019-05-05 17:22:13
【问题描述】:

我有一个 div,其中有多个 SVG 元素充当按钮,div 及其元素都是在页面加载后添加的,用户做了一些工作。 我想向 SVG 元素添加事件,因此使用事件委托,我得到事件然后检查它的目标。 问题是当我尝试这个时一切正常。但是当我单击元素时:

e.target 属性有时返回 SVG 元素,有时返回路径元素。

我想出了一个解决方法,在每个按钮的事件处理程序中使用 2 个条件,以及检查父级或元素 ID,它有效,但我想知道为什么会这样。 我能想到的最好的事情是路径代表图标的边界,但我不确定。

如果我为我的图标使用了<i> 标签,我会遇到同样的问题吗?

编辑:

var secondCondition = (e.target.tagName === 'path' && e.target.parentElement.id === 'icon-circle-with-minus');
if (e.target.matches('.servingsDecrease *, .servingsDecrease') || secondCondition) {
     console.log('dec');
}

这段代码运行良好。

【问题讨论】:

  • 你能添加一些代码吗?
  • 我刚刚添加了一个sn-p。

标签: javascript html svg


【解决方案1】:

e.target 属性有时返回 SVG 元素,有时返回路径元素。

这正是它的工作方式。 e.target 表示“接收”事件的元素,在大多数情况下,它是元素的某个嵌套子元素,事件侦听器附加到该元素。

查看here,了解有关事件冒泡/捕获的更多详细信息,以了解此类事件的工作原理。

基本上你只需要像这样向整个页面添加一个事件监听器:

window.addEventListener('click', e => console.log(e.target));

捕捉页面上的每次点击。从那里开始,您需要一种将事件委托给适当处理程序的方法。我经常发现自己对这样的解决方案感到满意:

示例 HTML

<div class="btns">
  <div data-click-handler="btn">
    <span>
      <p>some sample content</p>
    </span>
  </div>
  <div data-click-handler="btn2">
   <ul>
    <li>…</li>
   </ul>
  </div>
</div>

JS

const handlers = {
  btn: e => alert('btn clicked'),
  btn2: e => alert('btn2 clicked')
}

window.addEventListener('click', e => {
  let 
    c = e.target,
    //that could be an array as well
    //if you want all the handlers on
    //»way upwards« to be called
    handler = null
  ;

  //as long as there is a Node
  while (c && c.hasAttribute) {
    //check if it should listen to events
    if (c.hasAttribute('data-click-handler')) {
      //get the handler if it exists
      let key = c.getAttribute('data-click-handler');
      if (handlers.hasOwnProperty(key)) {
        handler = handlers[key];
        //break the loop to keep the reference to
        //»desired target«
        break;
      }
    }
    //go upwards in the tree
    c = c.parentNode;
  }

  //finally call the handler, if any
  if (handler !== null) handler(c);
});

这只是实现事件委托的一种方式的说明/概述,以克服为每个元素注册一个专用事件处理程序以触发一些事件代码的需要。如果您有一大堆元素需要响应某些事件,您可能需要这种技术来克服性能问题。

基本上有很多方法可以做到这一点,另一种使用&lt;element&gt;.matches() API 的方法被描述为here

【讨论】:

  • 最后一次编辑我添加了一个代码 sn-p 允许我成功捕获事件,我想知道为什么我有时会收到 path 而有时会收到 svg 元素。关于您的代码的旁注,我认为使用最接近()方法会更方便。 e.target.closest('div[data-click-handler]')
  • 事件的target 是接收事件的节点,并且必须是事件注册到的节点。由于内联 SVG 只是 DOM 的常规部分,如果您单击它们,&lt;path&gt; 元素将成为目标。我认为讨论获取“最近”元素的各种方法并不重要,因为搜索 DOM 树“向上”很重要。
【解决方案2】:

使用事件的currentTarget 属性而不是targetcurrentTarget 是事件附加到的元素。运行下面的 sn-p 并单击不同的元素以查看它的运行情况。

我意识到这可能没有帮助 - 有点难以辨别 wjen 以及从您的帖子中添加事件处理程序的位置。如果不是,请告诉我,我将删除此答案。

function clickHandler(e){
  console.log('target: ', e.target.tagName);
  console.log('currentTarget: ',e.currentTarget.tagName);
}
<svg width="80px" height="80px" viewBox="0 0 80 80" style="background:green;" onclick="clickHandler(event)">
  <path d="M0,0 L20,0 L20,20 L0,20 Z" fill="red"/>
  <circle cx="40" cy="40" r="15" fill="blue"/>
</svg>

【讨论】:

    猜你喜欢
    • 2013-09-09
    • 2013-05-04
    • 2019-12-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-20
    • 2013-09-20
    • 1970-01-01
    相关资源
    最近更新 更多