JavaScript - присоединение обработчиков событий к элементу также присоединяет их к его дочерним элементам - PullRequest
0 голосов
/ 26 ноября 2018

У меня есть этот HTML.Я хочу прикрепить события mouseover и mouseleave ТОЛЬКО к элементу .parent, но по какой-то причине они также привязываются к дочерним элементам, и я получаю странное поведение.

<div class="parent">
  <div class="child-1"></div>
  <div class="child-2"></div>
</div>

Вот как я это делаю

const parent = document.getElementsByClassName('parent')[0]
parent.addEventListener('mouseover', eventHandler)
parent.addEventListener('mouseleave', eventHandler)

Что происходит и как это предотвратить?

Ответы [ 4 ]

0 голосов
/ 26 ноября 2018

Это связано с тем, как работает перехват и всплытие событий.Я скопировал ответ @ACD, чтобы убедиться, что он ведет себя по-другому.Если вы заметили, что мы наведем курсор на дочерний элемент и переместимся к родительскому элементу, событие в этом примере не вызывается.Таким образом, дочерние элементы больше не являются целью события.

Существует две фазы события: ловля и выдувание.Вы можете найти больше информации здесь .То, что происходит, это событие запускается для ребенка, и оно пузырится на родителя.Вы можете проверить цель события с помощью event.target

. Если мы удалим pointer-events: none;, то целью будет дочерний элемент, а не родитель.и после того, как дочерний обработчик вызван, вентиляция передается родителю, а затем вызывается обратный вызов родителей.

const parent = document.getElementsByClassName('parent')[0]
parent.addEventListener('mouseover', eventHandler)
parent.addEventListener('mouseleave', eventHandler)

 

function eventHandler(e) {
  console.log(e.target, 'hey');
}
<div class="parent" style="width: 25px; height: 25px; background: red; padding: 50px">
  <div class="child-1" style="pointer-events: none; width: 25px; height: 25px; background: blue"></div>
  <div class="child-2" style="pointer-events: none; width: 25px; height: 25px; background: green"></div>
</div>
0 голосов
/ 26 ноября 2018

Попробуйте mouseenter и mouseleave вместо mouseover и mouseleave.Не путай их.Это либо комбинация mouseover/mouseout, либо mouseenter/mouseleave, потому что эти комбинации симметричны.

https://developer.mozilla.org/en-US/docs/Web/Events/mouseenter

var logs = document.querySelector('.log');
var area = document.querySelector('.parent');

function eventHandler (e) {
  if (e.type === 'mouseenter') {
    area.style.backgroundColor = '#c00';
  } else {
    area.style.backgroundColor = '';
  }
}

area.addEventListener('mouseenter', eventHandler);
area.addEventListener('mouseleave', eventHandler);
.parent {
  background: #eee;
}
.child {
  padding: 30px 20px;
}
.child + .child {
  border-top: 1px dotted #333;
}
<div class="parent">
  <div class="child">
    foo bar baz
  </div>
  <div class="child">
    foo bar baz
  </div>
</div>
0 голосов
/ 26 ноября 2018

Вы можете исправить это с помощью css, применив

.child-1, .child-2 {
  pointer-events: none
}

к детям, таким образом, взаимодействие с детьми невозможно.

В качестве альтернативы, в обработчике событий вы можете проверить, еслиevent.target является родителем или дочерним узлом; при наведении курсора на дочерний узел будет получен дочерний узел, при наведении курсора на .parent будет отображаться родительский элемент.

0 голосов
/ 26 ноября 2018

Необходимо добавить событие в дочерние узлы и отменить распространение события.

const parent = document.getElementsByClassName('parent')[0]
parent.addEventListener('mouseover', eventHandler)
parent.addEventListener('mouseleave', eventHandler)

for (const child of parent.childNodes) {
  child.addEventListener('mouseover', function(event) {
    event.stopPropagation();
  })
  child.addEventListener('mouseleave', function(event) {
    event.stopPropagation();
  })
}

function eventHandler() {
  console.log('hey');
}
<div class="parent" style="width: 25px; height: 25px; background: red; padding: 50px">
  <div class="child-1" style="width: 25px; height: 25px; background: blue"></div>
  <div class="child-2" style="width: 25px; height: 25px; background: green"></div>
</div>

Или вы можете делать то, что все хотят pointer-event

const parent = document.getElementsByClassName('parent')[0]
parent.addEventListener('mouseover', eventHandler)
parent.addEventListener('mouseleave', eventHandler)

for (const child of parent.childNodes) {
  child.className += ' no-event'
}

function eventHandler() {
  console.log('hey');
}
.no-event {
  pointer-events: none;
}
<div class="parent" style="width: 25px; height: 25px; background: red; padding: 50px">
  <div class="child-1" style="width: 25px; height: 25px; background: blue"></div>
  <div class="child-2" style="width: 25px; height: 25px; background: green"></div>
</div>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...