Почему событие родительского элемента запускается при нажатии на дочерний элемент? [Дубликат]

Конечно, есть много таких подходов, как синхронный запрос, обещание, но из моего опыта я думаю, что вы должны использовать подход обратного вызова. Естественно, что асинхронное поведение Javascript. Итак, ваш фрагмент кода можно переписать немного иначе:

function foo() {
    var result;

    $.ajax({
        url: '...',
        success: function(response) {
            myCallback(response);
        }
    });

    return result;
}

function myCallback(response) {
    // Does something.
}
835
задан bjb568 13 April 2015 в 00:44
поделиться

5 ответов

Банкротство и захват событий - два способа распространения события в API DOM HTML, когда событие происходит в элементе внутри другого элемента, и оба элемента зарегистрировали дескриптор для этого события. Режим распространения событий определяет в , который упорядочивает элементы, получающие событие .

При барботировании событие сначала захватывается и обрабатывается самым внутренним элементом, а затем распространяется на внешние элементы.

С захватом событие сначала захватывается самым внешним элементом и распространяется на внутренние элементы.

Захват также называется «trickling», что помогает запомнить порядок распространения:

trickle down, bubble up

. В прежние времена Netscape отстаивал захват событий, в то время как Microsoft продвигала пузыри событий. Оба являются частью стандарта W3C Events Object Model Model (2000).

IE & lt; 9 использует только событие bubbling события , тогда как IE9 + и все основные браузеры поддерживают оба. С другой стороны, производительность барботажа событий может быть несколько ниже для сложных DOM.

Мы можем использовать addEventListener(type, listener, useCapture) для регистрации обработчиков событий в обоих вариантах барботажа (по умолчанию) или режим захвата.

Пример

<div>
    <ul>
        <li></li>
    </ul>
</div>

В вышеприведенной структуре предположим, что событие click произошло в элементе li.

При захвате модели событие будет обработано сначала div (сначала будут запускаться обработчики событий в div), затем в ul, а затем на последнем в целевом элемент li.

В модели барботирования произойдет обратное: событие будет обрабатываться в первую очередь li, затем ul и, наконец, div Элемент.

Для получения дополнительной информации см.

В приведенном ниже примере, если вы нажмете на любой из выделенных элементов, вы увидите, что сначала происходит фаза захвата потока распространения события, затем фаза барботирования.

var logElement = document.getElementById('log');

function log(msg) {
    logElement.innerHTML += ('<p>' + msg + '</p>');
}

function capture() {
    log('capture: ' + this.firstChild.nodeValue.trim());
}

function bubble() {
    log('bubble: ' + this.firstChild.nodeValue.trim());
}

var divs = document.getElementsByTagName('div');
for (var i = 0; i < divs.length; i++) {
    divs[i].addEventListener('click', capture, true);
    divs[i].addEventListener('click', bubble, false);
}
p {
    line-height: 0;
}

div {
    display:inline-block;
    padding: 5px;

    background: #fff;
    border: 1px solid #aaa;
    cursor: pointer;
}

div:hover {
    border: 1px solid #faa;
    background: #fdd;
}
<div>1
    <div>2
        <div>3
            <div>4
                <div>5</div>
            </div>
        </div>
    </div>
</div>
<section id="log"></section>

Другой пример в JSFiddle .

1158
ответ дан Hristiyan Dodov 24 August 2018 в 09:53
поделиться

Также существует свойство Event.eventPhase , которое может сказать вам, находится ли событие в целевой точке или происходит откуда-то еще.

Обратите внимание, что совместимость браузера еще не определена. Я тестировал его на Chrome (66.0.3359.181) и Firefox (59.0.3), и он поддерживается там.

Развернув на уже отличный фрагмент из принятого ответа , это результат с использованием свойства eventPhase

var logElement = document.getElementById('log');

function log(msg) {
  if (logElement.innerHTML == "<p>No logs</p>")
    logElement.innerHTML = "";
  logElement.innerHTML += ('<p>' + msg + '</p>');
}

function humanizeEvent(eventPhase){
  switch(eventPhase){
    case 1: //Event.CAPTURING_PHASE
      return "Event is being propagated through the target's ancestor objects";
    case 2: //Event.AT_TARGET
      return "The event has arrived at the event's target";
    case 3: //Event.BUBBLING_PHASE
      return "The event is propagating back up through the target's ancestors in reverse order";
  }
}
function capture(e) {
  log('capture: ' + this.firstChild.nodeValue.trim() + "; " + 
  humanizeEvent(e.eventPhase));
}

function bubble(e) {
  log('bubble: ' + this.firstChild.nodeValue.trim() + "; " + 
  humanizeEvent(e.eventPhase));
}

var divs = document.getElementsByTagName('div');
for (var i = 0; i < divs.length; i++) {
  divs[i].addEventListener('click', capture, true);
  divs[i].addEventListener('click', bubble, false);
}
p {
  line-height: 0;
}

div {
  display:inline-block;
  padding: 5px;

  background: #fff;
  border: 1px solid #aaa;
  cursor: pointer;
}

div:hover {
  border: 1px solid #faa;
  background: #fdd;
}
<div>1
  <div>2
    <div>3
      <div>4
        <div>5</div>
      </div>
    </div>
  </div>
</div>
<button onclick="document.getElementById('log').innerHTML = '<p>No logs</p>';">Clear logs</button>
<section id="log"></section>

0
ответ дан Adelin 24 August 2018 в 09:53
поделиться

Если есть два элемента: элемент 1 и элемент 2. Элемент 2 находится внутри элемента 1, и мы присоединяем обработчик событий, в котором оба элемента позволяют говорить onClick. Теперь, когда мы нажимаем на элемент 2, будет выполняться eventHandler для обоих элементов. Теперь здесь возникает вопрос, в каком порядке будет выполняться событие. Если событие, связанное с элементом 1, выполняется первым, оно называется захватом события, и если событие, связанное с элементом 2, выполняется первым, это называется барботированием событий. Согласно W3C событие начнется на этапе захвата до тех пор, пока оно не достигнет цели, возвращается к элементу, а затем начинает пузыриться

Состояние захвата и пузырения известно с помощью параметра useCapture метода addEventListener

eventTarget.addEventListener (type, listener, [, useCapture]);

По умолчанию useCapture является ложным. Это означает, что он находится в фазе барботирования.

var div1 = document.querySelector("#div1");
var div2 = document.querySelector("#div2");

div1.addEventListener("click", function (event) {
  alert("you clicked on div 1");
}, true);

div2.addEventListener("click", function (event) {
  alert("you clicked on div 2");
}, false);
#div1{
  background-color:red;
  padding: 24px;
}

#div2{
  background-color:green;
}
<div id="div1">
  div 1
  <div id="div2">
    div 2
  </div>
</div>

Попробуйте изменить true и false.

63
ответ дан dinesh_malhotra 24 August 2018 в 09:53
поделиться

Описание:

quirksmode.org имеет хорошее описание этого. В двух словах (скопировано из quirksmode):

Запись события

Когда вы используете захват события

               | |
---------------| |-----------------
| element1     | |                |
|   -----------| |-----------     |
|   |element2  \ /          |     |
|   -------------------------     |
|        Event CAPTURING          |
-----------------------------------

, обработчик события element1 срабатывает первым , обработчик события element2 срабатывает последним.

Событие bubbling

Когда вы используете барботирование событий

               / \
---------------| |-----------------
| element1     | |                |
|   -----------| |-----------     |
|   |element2  | |          |     |
|   -------------------------     |
|        Event BUBBLING           |
-----------------------------------

, сначала запускается обработчик события element2, событие обработчик элемента1 срабатывает последним.


Что использовать?

Это зависит от того, что вы хотите сделать. Нет лучшего. Разница заключается в порядке выполнения обработчиков событий. В большинстве случаев будет нормально запускать обработчики событий на фазе bubbling , но также может потребоваться их запуск раньше.

458
ответ дан Felix Kling 24 August 2018 в 09:53
поделиться

Я нашел это учебник на javascript.info , чтобы быть очень ясным в объяснении этой темы. И его 3-балльное резюме в конце действительно разговаривает с критическими моментами. Я цитирую его здесь:

  1. События сначала захватываются до самой глубокой цели, а затем пузырятся. В IE & lt; 9 они только пузырьки.
  2. Все обработчики работают на стадии барботирования, кроме addEventListener с последним аргументом true, что является единственным способом поймать событие на этапе захвата.
  3. Bubbling / capture можно остановить event.cancelBubble = true (IE) или event.stopPropagation () для других браузеров.
23
ответ дан gm2008 24 August 2018 в 09:53
поделиться
Другие вопросы по тегам:

Похожие вопросы: