Проблема с делегированием события - PullRequest
1 голос
/ 02 февраля 2020

Я работаю с плагином mapbox geocoder, который представляет собой панель поиска, которая заполняет подсказки мест во время ввода и отображает их в раскрывающемся списке. По сути, я работаю с элементами списка Dynami c. Я пытаюсь использовать делегирование событий, поэтому, когда я нажимаю на элемент списка, запускается созданная мной функция.

Нет ничего плохого в моей функции, так как я использую ее где-то еще. Я решил попробовать console.log("Li has been clicked!!"), чтобы проверить, идентифицирует ли элемент списка мой 'click'. Это не так и никаких ошибок не выдается в консоли. Так что я не уверен, что именно не так.

Ниже приведен фрагмент html, который генерируется динамически, и моя попытка делегирования события. Любая помощь в определении того, что не так, будет принята с благодарностью. Спасибо.

HTML:

<div class="suggestions-wrapper">
    <ul class="suggestions" style="display: none;">
        <li class=" active">
            <a>
                <div class="mapboxgl-ctrl-geocoder--suggestion">
                    <div class="mapboxgl-ctrl-geocoder--suggestion-title">844 Napa Valley Drive</div>
                    <div class="mapboxgl-ctrl-geocoder--suggestion-address"> Fort Collins, Colorado 80525, United States of America</div>
                </div>
            </a>
        </li>
        <li>
            <a>
                <div class="mapboxgl-ctrl-geocoder--suggestion">
                    <div class="mapboxgl-ctrl-geocoder--suggestion-title">844 Courtenay Circle</div>
                    <div class="mapboxgl-ctrl-geocoder--suggestion-address"> Fort Collins, Colorado 80525, United States of America</div>
                </div>
            </a>
        </li>
    </ul>
</div>

JS:

document.getElementsByClassName('suggestions')[0].addEventListener('click', function(e) {
    if(e.target && e.target.nodeName == "LI") {
        plotIso();
        console.log("Li has been clicked!!")
    }
})

Решение:

I изменил 'click' на 'mouseup' в моем приложении, а также 'LI' на 'DIV', как предложено @Menelaos Bakopoulos. Не уверен, почему он принимает «mouseup», а не «click». Я предполагаю, что это как-то связано с тем, как кодируется плагин геокода mapbox.

var searchSugg = document.getElementsByClassName('suggestions')[0];
searchSugg.addEventListener('mouseup', function(e) {
    if(e.target && e.target.nodeName == "DIV") {
        plotIso();
        console.log("Li has been clicked!!")
    }
});

Ответы [ 2 ]

1 голос
/ 02 февраля 2020

Помещение условия в «LI» означает, что вы должны щелкнуть действительную точку. Если вы не нажмете пулю или точку, ничего не произойдет.

Вам необходимо изменить это условие.

Я прокомментировал ваше утверждение IF, и это отображает добавленный console.log и предупреждение.

document.getElementsByClassName('suggestions')[0].addEventListener('click', function(e) {
    //if(e.target && e.target.nodeName == "LI") {
       alert("Li has been clicked!!")
        console.log("Li has been clicked!!")
   // }
})

Fiddle: https://jsfiddle.net/menelaosbgr/ftbpyLr9/3/

Обновление

Как указано в OP, изменение LI на DIV решает проблему:

 document.getElementsByClassName('suggestions')[0].addEventListener('click', function(e) {
        //if(e.target && e.target.nodeName == "DIV") {
           alert("Li has been clicked!!")
            console.log("Li has been clicked!!")
       // }
    })
0 голосов
/ 02 февраля 2020

Поскольку вам не обязательно нажимать DOT или BULLET из LI , вы можете нажать a>, div> (потомки li>) . Таким образом, условие e.target.nodeName == "LI" недостаточно хорошее. Я рекомендую вам следующий фрагмент:

function findClosest(el, selector) {
    if (!Element.prototype.closest) { // Older browsers
        let e = el;
        while (e) {
            if (selectorMatches(e, selector)) {
                return e;
            }
            e = e.parentElement;
        }
    }
    // Modern browsers
    return el.closest(selector);
}

document.getElementsByClassName('suggestions')[0].addEventListener('click', function(e) {
    let ele = e.target; // ele is always available here because the event click is fired
    let liClicked = findClosest(ele, 'li'); // get enclosed <LI> of ele clicked
    if(liClicked) {
        plotIso();
        console.log("Li has been clicked!!", liClicked);
    }
})
...