簡體   English   中英

單擊父項的子項時的事件偵聽器

[英]Event listener for when child of parent is clicked

我目前有一個問題,我希望能夠檢查單擊事件的時間。 我想為此使用事件委托,因此我在父 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>

我希望能夠在單擊右側 div 時獲取data-page屬性,即單擊 div dashboard-shortcut時。 有什么辦法可以做到這一點嗎?

非常感謝您提前。

除非您希望動態添加元素,否則不要使用事件委托,只需在每個目標上附加一個偵聽器,在本例中為.side-nav > [data-page]元素。

這樣您就可以避免所有檢測問題,例如單擊哪個實際div等, this將是目標元素,例如this.dataset.page

...和獎金; 更少的代碼,更不容易出錯,更容易維護。

注意,你使用data.set.param應該是dataset.param ,這里的parampage ( 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>

// 使用最接近的方法來查找實際元素

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>

事件的target屬性將是單擊的元素。 在您的場景中,單擊的元素可以是您在示例中顯示的任何 HTML 元素: .side-nav-button內的pi.side-nav-button本身,甚至是您附加的.side-nav事件。

我能想到的是獲取目標元素,檢查是否有data-page屬性,如果沒有,則為父元素 go 並重復檢查。 這樣,例如,如果單擊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);
    }
});

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM