Прослушиватель событий, когда нажимается дочерний элемент родителя - PullRequest
1 голос
/ 29 сентября 2019

В настоящее время у меня есть проблема, из-за которой я хочу проверить, когда происходит щелчок по событию. Я хочу использовать делегирование событий для этого, и поэтому я настроил прослушиватель событий в родительском div, который прослушивает щелчки:

document.querySelector('.side-nav').addEventListener('click', e => {
    console.log(e.target.data.set.param);
});

Это мой DOM:

<div class="side-nav">
    <div class="side-nav-button side-nav-active pointer" id="dashboard-shortcut" title="Home" data-page="dashboard">
        <p class="side-nav-button-icon"><i class="fas fa-home"></i></p>
    </div>
    <div class="side-nav-button side-nav-active pointer" id="another-div-shortcut" title="page2" data-page="page2">
        <p class="side-nav-button-icon"><i class="fas fa-cross"></i></p>
    </div>
</div>

Iхотите иметь возможность получить атрибут data-page при нажатии правого элемента div, то есть при нажатии элемента div dashboard-shortcut. Есть ли способ, которым я могу это сделать?

Заранее большое спасибо.

Ответы [ 3 ]

2 голосов
/ 29 сентября 2019

Если вы не предполагаете, что элементы будут добавлены динамически, не используйте делегирование событий, просто подключите прослушиватель к каждой цели, в этом случае к элементам .side-nav > [data-page].

Благодаря этому вы избежите всех проблем обнаружения,например, какой фактический div был выбран и т. д., где this будет целевым элементом, например, this.dataset.page.

... и бонус;меньше кода, меньше ошибок, более простое обслуживание.

Обратите внимание, что вы использовали data.set.param, должно быть dataset.param, где param здесь page (data-page)

Фрагмент стека

document.querySelectorAll('.side-nav > [data-page]').forEach(el => {
  el.addEventListener('click', function() {
    console.log(this.dataset.page);
  });
});
<div class="side-nav">
    <div class="side-nav-button side-nav-active pointer" id="dashboard-shortcut" title="Home" data-page="dashboard">
        <p class="side-nav-button-icon"><i class="fas fa-home">Home</i></p>
    </div>
    <div class="side-nav-button side-nav-active pointer" id="another-div-shortcut" title="page2" data-page="page2">
        <p class="side-nav-button-icon"><i class="fas fa-cross">Page2</i></p>
    </div>
</div>

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

Использование if (e.target !== this && this.contains(e.target))мы можем проверить, чтобы кто-то нажал не на .side.nav (e.target !== this), а на одного из его потомков (this.contains(e.target)), прежде чем продолжить.

И если при e.target.closest('[data-page]').dataset.page мы получимцелевой элемент.

Обратите внимание, как уже упоминалось в другом комментарии, если вы вложили .side-nav в дочерние элементы, имеющие одинаковые классы / атрибут, вам может потребоваться настроить, например, расширение селектора для closest(), до closest('.side-nav > [data-page]'), должно быть достаточно, однако трудно сказать с уверенностью.

Фрагмент стека

document.querySelector('.side-nav').addEventListener('click', function(e) {
  if (e.target !== this && this.contains(e.target)) {    
    console.log(e.target.closest('[data-page]').dataset.page);  
  }
});
<div class="side-nav">
    <div class="side-nav-button side-nav-active pointer" id="dashboard-shortcut" title="Home" data-page="dashboard">
        <p class="side-nav-button-icon"><i class="fas fa-home">Home</i></p>
    </div>
    <div class="side-nav-button side-nav-active pointer" id="another-div-shortcut" title="page2" data-page="page2">
        <p class="side-nav-button-icon"><i class="fas fa-cross">Page2</i></p>
    </div>
</div>
0 голосов
/ 29 сентября 2019

Свойство target события будет выбранным элементом. В вашем сценарии выбранный элемент может быть любым элементом HTML, который вы показали в своем примере: p или i внутри .side-nav-button, сам .side-nav-button или даже .side-nav, где вы прикрепляете событие.

Я могу подумать о том, чтобы получить целевой элемент, проверить наличие атрибута data-page, а если нет, перейти к родительскому элементу и повторить проверку. Таким образом, если, например, щелкнуть элемент i, он проверит сам себя, затем проверит p и, наконец, его .side-nav-button.

Следовательно:

document.querySelector('.side-nav').addEventListener('click', e => {
    let el = e.target;
    // The loop will stop when there's a page dataset
    // Also will stop when the element that is checking is .side-nav (event.currentTarget), as there's no need to check beyond that.
    while(el && el != event.currentTarget && !el.dataset.hasOwnProperty("page")) {
        el = el.parentNode;
    }
    let page = el && el.dataset.page;
    if (page) {
        console.log(page);
    }
});
0 голосов
/ 29 сентября 2019

// использовать ближайший метод для поиска фактического элемента

document.querySelector('.side-nav').addEventListener('click', e => {
    var elem = e.target.closest("[data-page]");
    if (elem && elem.getAttribute('data-page') !== 'root') {
        console.log(elem.getAttribute("data-page"));
    }
});

Примечание: запретить поиск элемента до корня

<div class="side-nav" data-page='root'>
    <div class="side-nav-button side-nav-active pointer" id="dashboard-shortcut" title="Home" data-page="dashboard">
        <p class="side-nav-button-icon"><i class="fas fa-home"></i></p>
    </div>
   <div class="side-nav-button side-nav-active pointer" id="another-div-shortcut" title="page2" data-page="page2">
        <p class="side-nav-button-icon"><i class="fas fa-cross"></i></p>
    </div>
</div>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...