繁体   English   中英

JS-子元素不监听委托事件

[英]JS - Child element to not listen to delegated event

在以下代码段中,您将看到一个附加到document的委托事件。

要注意的关键是:

if (e.target.parentNode.id === 'put-stuff-here') {
  e.target.classList.toggle('active');
}

 function loadItems(target) { for (var i = 0; i < 10; i++) { setTimeout(function() { target.insertAdjacentHTML('beforeend', '<div class="new"><span>Click me!</span>Or click me!</div>'); }, (i * 250)); } } document.getElementsByTagName('button')[0].addEventListener('click', function(e) { loadItems(document.getElementById('put-stuff-here')); }); document.addEventListener('click', function(e) { if (e.target.parentNode.id === 'put-stuff-here') { e.target.classList.toggle('active'); } }); 
 body { font-family: 'arial'; display: flex; flex-flow: column; } body > * { margin-bottom: 16px; } #put-stuff-here:before { display: block; padding: 8px; text-align: center; content: 'Target Location:'; background-color: PapayaWhip; } #put-stuff-here { border: 1px solid black; } .new { background-color: SteelBlue; padding: 8px; } .new span { border: 1px dotted red; margin: 8px; } .active { background-color: white; } 
 <button>Press Me!</button> <div id="put-stuff-here"> </div> 

如您所见,如果您单击“红色边框范围”,它将不起作用,但是如果您单击div,它将起作用。 我知道原因,“解决方案”是:

if (e.target.parentNode.id === 'put-stuff-here' || e.target.parentNode.parentNode.id === 'put-stuff-here') {
  e.target.classList.toggle('active');
}

这个; 但是,它不能完全起作用,并且会导致这种情况(在span和div上均单击):

 function loadItems(target) { for (var i = 0; i < 10; i++) { setTimeout(function() { target.insertAdjacentHTML('beforeend', '<div class="new"><span>New!</span></div>'); }, (i * 250)); } } document.getElementsByTagName('button')[0].addEventListener('click', function(e) { loadItems(document.getElementById('put-stuff-here')); }); document.addEventListener('click', function(e) { if (e.target.parentNode.id === 'put-stuff-here' || e.target.parentNode.parentNode.id === 'put-stuff-here') { e.target.classList.toggle('active'); } }); 
 body { font-family: 'arial'; display: flex; flex-flow: column; } body > * { margin-bottom: 16px; } #put-stuff-here:before { display: block; padding: 8px; text-align: center; content: 'Target Location:'; background-color: PapayaWhip; } #put-stuff-here { border: 1px solid black; } .new { background-color: SteelBlue; padding: 8px; } .new span { border: 1px dotted red; margin: 8px; } .active { background-color: white; } 
 <button>Press Me!</button> <div id="put-stuff-here"> </div> 

我测试了多种其他方法,包括:

if (e.target.parentNode.id === 'put-stuff-here' || e.target.parentNode.parentNode.id === 'put-stuff-here') {
  e.target.classList.toggle('active') || e.target.parentNode.classList.toggle('active');
}

但是它们都不满足我的要求,即: 当您在div单击任意位置时,它将切换active

我认为解决方案位于事件冒泡的某个地方,但我一直无法找到一种利用此事件的方法。 是否有子事件可以“忽略”(未授权)事件的事件处理程序的方法?

一个jsfiddle可以在这里找到。

PS我知道另一种方法是:

if (e.target.classList.contains('new') || e.target.parentNode.classList.contains('new')) {
  e.target.classList.toggle('active');
}

以及所有其他变体等,但是遇到了我上面列出的相同问题。

我认为解决方案位于事件冒泡的某个地方,但我一直无法找到一种利用此事件的方法。 是否有子事件可以“忽略”(未授权)事件的事件处理程序的方法?

是的,事件冒泡是解决方案的一部分,利用event.targetevent.currentTarget的属性将帮助您隔离事件链中的特定元素。

SNIPPET

 // Reference the parent element var parent = document.getElementById('parent'); // add an eventListener to the parent element parent.addEventListener('click', function(event) { /* | While in bubbling phase, we only want event.target | (ie the element that was clicked on) and not | all of the other elements that happen to be on the | event chain (ie event.currentTarget) */ if (event.target !== event.currentTarget) { // Store the event.target in a var var tgt = event.target; // Do whatever you want to event.target tgt.classList.toggle('active'); } /* | Stop any further bubbling so that event.target is | the only element on the event chain that reacts to | the click event. */ event.stopPropagation(); }, false); 
 #parent { background: rgba(0, 0, 0, .75); border: 3px dashed red; padding: 10px; } .child { background: rgba(255, 255, 255, .75); border: 1px solid blue; margin: 5px; height: 15px; } .active { background: red; outline: 2px dotted orange; } 
 <main id='parent'> <section class='child'></section> <section class='child'></section> <section class='child'></section> <section class='child'></section> <section class='child'></section> <section class='child'></section> <section class='child'></section> <section class='child'></section> <section class='child'></section> <section class='child'></section> </main> 

您可以使用pointer-events

CSS属性pointer-events允许作者控制在什么情况下(如果有的话)特定的图形元素可以成为鼠标事件的目标。

.new > * {
  pointer-events: none;
}

 function loadItems(target) { for (var i = 0; i < 10; i++) { setTimeout(function() { target.insertAdjacentHTML('beforeend', '<div class="new"><span>Click me!</span>Or click me!</div>'); }, (i * 250)); } } document.getElementsByTagName('button')[0].addEventListener('click', function(e) { loadItems(document.getElementById('put-stuff-here')); }); document.addEventListener('click', function(e) { if (e.target.parentNode.id === 'put-stuff-here') { e.target.classList.toggle('active'); } }); 
 body { font-family: 'arial'; display: flex; flex-flow: column; } body > * { margin-bottom: 16px; } #put-stuff-here:before { display: block; padding: 8px; text-align: center; content: 'Target Location:'; background-color: PapayaWhip; } #put-stuff-here { border: 1px solid black; } .new { background-color: SteelBlue; padding: 8px; } .new > span { border: 1px dotted red; margin: 8px; pointer-events: none; } .active { background-color: white; } 
 <button>Press Me!</button> <div id="put-stuff-here"> </div> 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM