父节点上的事件侦听器也在所有子节点上触发

时间:2019-02-06 22:23:22

标签: javascript ecmascript-6 addeventlistener getelementsbyclassname stoppropagation

我正在从头开始在Vanilla js中编写一个可拖动类(这与jQuery可拖动无关),而且效果很好,只有我的侦听器在选定节点的子节点上触发。我已经在听众内部尝试过pip install cairocffi,但似乎并没有改变结果。

以下是该类的代码段:

e.stopPropagation()

...,例如:

setListeners() {

    const targets = document.getElementsByClassName("-jsDraggable");

    [...targets].forEach(elem => {

        elem.addEventListener("mousemove", e => this.handleMouseMove(e));
        elem.addEventListener("mousedown", e => this.handleMouseDown(e));
        elem.addEventListener("mouseup", e => this.handleMouseUp(e));

    });
}

在这种情况下,我希望同时影响<ul class="-jsDraggable"> <li>No drag</li> <li>No drag</li> <li class="-jsDraggable">Can drag this item</li> <li>No drag</li> </ul> 和里面的单个<ul class="-jsDraggable">...</ul>,在其中从其他列表项之一拖动将仅拖动主<li class="-jsDraggable">...</li>元素

但是,无论我与哪个子节点进行交互,无论它在DOM中与具有类的节点相比有多远,它都会触发处理程序。

任何帮助将不胜感激!

编辑:另一个要阐明的例子:

<ul class="-jsDraggable">...</ul>

无论我将这个<article class="-jsDraggable"> <header> <h1>Heading</h1> </header> <main> <p>...</p> </main> </article> 元素拖到哪里,它都应该将整个HTML组作为一个组拖动(因为所有的父级都有该类)。但是,目前,它的行为更像是这样:

<article>

...并且每个单独的孩子也在移动时,应该只移动附加了类的父容器。

2 个答案:

答案 0 :(得分:0)

我解决了它,因为我将当前元素设置为this.elem = e.target而不是this.elem = e.currentTarget,所以它不起作用。此后,鼠标右键中的e.stopPropagation()如期工作。

感谢您将我介绍给e.currentTarget,在阅读此线程中的帮助之前,我并不知道。

答案 1 :(得分:-1)

如果我正确理解了您的问题,那么(其中一个)选择是区分事件的起源,并通过{{1}的currentTargettarget字段过滤事件处理}对象如下:

event

这实际上意味着,如果产生事件的元素(即if(event.currentTarget === event.target) { /* The user is interacting with the actual -jsDraggable element */ } else { /* The user is interacting with a descendant of a -jsDraggable element */ } )与事件处理程序已绑定到的元素(即currentTarget)相同,则我们确定该事件与实际的target元素本身有关(而不与后代有关)。这种方法补充了您当前的代码,如下所示:

-jsDraggable
function handleMouseMove(event) {
  if(event.currentTarget === event.target) {
    console.log(Date.now(), 'Mouse move over draggable');
  }
}
function handleMouseDown(event) {
  if(event.currentTarget === event.target) {
    console.log(Date.now(), 'Drag start on draggable');
  }
}
function handleMouseUp(event) {
  if(event.currentTarget === event.target) {
    console.log(Date.now(), 'Drag end on draggable');
  }
}

function setListeners() {

    const targets = document.querySelectorAll(".-jsDraggable");

    targets.forEach(elem => {

        elem.addEventListener("mousemove", e => handleMouseMove(e));
        elem.addEventListener("mousedown", e => handleMouseDown(e));
        elem.addEventListener("mouseup", e => handleMouseUp(e));

    });
}

setListeners();
ul {
  padding:1rem;
  background:lightgreen;
}
li {
  padding:1rem;
  background:pink;
}
.-jsDraggable {
  background:lightblue;
}