Прослушиватель событий на родительском узле также запускается на всех дочерних узлах - PullRequest
0 голосов
/ 07 февраля 2019

Я пишу перетаскиваемый класс в vanilla js с нуля (это НЕ связано с перетаскиванием jQuery), и он работает отлично, только мои слушатели запускают дочерние элементы выбранного узла.Я пробовал 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> внутри, где перетаскивание из одного из других элементов списка просто перетянет основной <ul class="-jsDraggable">...</ul> element.

Однако, независимо от того, с каким дочерним узлом я взаимодействую, независимо от того, как далеко в DOM он сравнивается с узлом с классом, он запускает обработчики.

Любая помощь будет принята с благодарностью!

РЕДАКТИРОВАТЬ: Еще один пример для уточнения:

<article class="-jsDraggable">
    <header>
        <h1>Heading</h1>
    </header>
    <main>
        <p>...</p>
    </main>
</article>

Независимо от того, куда я перетаскиваю этот элемент <article>, он должен перетаскиватьвся группа HTML как единое целое (так как родительский объект всего этого имеет класс).Однако в настоящее время он работает примерно так:

<article class="-jsDraggable">
    <header class="-jsDraggable">
        <h1 class="-jsDraggable">Heading</h1>
    </header>
    <main class="-jsDraggable">
        <p class="-jsDraggable">...</p>
    </main>
</article>

... и каждый дочерний элемент также перемещается, когда он должен перемещать только родительский контейнер, к которому присоединен класс.

Ответы [ 2 ]

0 голосов
/ 07 февраля 2019

Я решил, это не сработало, потому что я установил текущий элемент как this.elem = e.target вместо this.elem = e.currentTarget.После этого e.stopPropagation() в mousedown работал как ожидалось.

Спасибо, что выставили меня на e.currentTarget, я не знал об этом до прочтения справки в этой теме.

0 голосов
/ 07 февраля 2019

Если я правильно понимаю ваш вопрос, то одна из опций (среди прочих) состоит в том, чтобы определить происхождение события и отфильтровать обработку события через поля currentTarget и target объекта 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;
}
<ul class="-jsDraggable">
    <li>No drag</li>
    <li>No drag</li>
    <li class="-jsDraggable">Can drag this item</li>
    <li>No drag</li>
</ul>
...