事件委托的问题
Trouble with event delegation
我正在使用 mapbox geocoder 插件,它是一个搜索栏,可在您键入并在下拉列表中显示时填充地点建议。本质上,我正在使用动态列表元素。我正在尝试使用事件委托,所以当我单击列表项时,我创建的函数被触发。
我的功能没有任何问题,因为我正在其他地方使用它。我决定尝试 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!!")
}
})
解法:
我在我的应用程序中将 'click'
更改为 'mouseup'
,并且还按照 @Menelaos Bakopoulos 的建议将 'LI'
更改为 'DIV'
。不确定为什么它接受 'mouseup' 而不是 'click'。我假设它与 mapbox geocode 插件的编码方式有关。
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!!")
}
});
将条件放在 "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!!")
// }
})
因为您不一定要点击 DOT or BULLET of 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);
}
})
我正在使用 mapbox geocoder 插件,它是一个搜索栏,可在您键入并在下拉列表中显示时填充地点建议。本质上,我正在使用动态列表元素。我正在尝试使用事件委托,所以当我单击列表项时,我创建的函数被触发。
我的功能没有任何问题,因为我正在其他地方使用它。我决定尝试 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!!")
}
})
解法:
我在我的应用程序中将 'click'
更改为 'mouseup'
,并且还按照 @Menelaos Bakopoulos 的建议将 'LI'
更改为 'DIV'
。不确定为什么它接受 'mouseup' 而不是 'click'。我假设它与 mapbox geocode 插件的编码方式有关。
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!!")
}
});
将条件放在 "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!!")
// }
})
因为您不一定要点击 DOT or BULLET of 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);
}
})