简体   繁体   English

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

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

In the following snippet you will see a delegated event attached to document . 在以下代码段中,您将看到一个附加到document的委托事件。

The key thing to note is: 要注意的关键是:

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> 

As you can see, if you click on the "red-bordered span" it will not work, but if you click on the div it works. 如您所见,如果您单击“红色边框范围”,它将不起作用,但是如果您单击div,它将起作用。 I know the reason for this and the "solution" is: 我知道原因,“解决方案”是:

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

This; 这个; however, does not fully work, and causes this (click on both the span and then the div): 但是,它不能完全起作用,并且会导致这种情况(在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> 

There are various other methods I have tested, including: 我测试了多种其他方法,包括:

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');
}

But they all do not do what I want, which is: when you click anywhere in the div , it will toggle the active class 但是它们都不满足我的要求,即: 当您在div单击任意位置时,它将切换active

I think the solution lies somewhere event bubbling, but I have not been able to find a way to utilize this. 我认为解决方案位于事件冒泡的某个地方,但我一直无法找到一种利用此事件的方法。 Is there a way for child events to "ignore" event handlers on (non-)delegated events? 是否有子事件可以“忽略”(未授权)事件的事件处理程序的方法?

A jsfiddle for this can be found here . 一个jsfiddle可以在这里找到。

PS I know another way to do this is: PS我知道另一种方法是:

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

and all the other variations, etc. but that runs into the same problem that I list above. 以及所有其他变体等,但是遇到了我上面列出的相同问题。

I think the solution lies somewhere event bubbling, but I have not been able to find a way to utilize this. 我认为解决方案位于事件冒泡的某个地方,但我一直无法找到一种利用此事件的方法。 Is there a way for child events to "ignore" event handlers on (non-)delegated events? 是否有子事件可以“忽略”(未授权)事件的事件处理程序的方法?

Yes event bubbling is part of the solution, and utilizing the properties of event.target and event.currentTarget will help you isolate a specific element along the event chain. 是的,事件冒泡是解决方案的一部分,利用event.targetevent.currentTarget的属性将帮助您隔离事件链中的特定元素。

SNIPPET 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> 

You can use pointer-events : 您可以使用pointer-events

The CSS property pointer-events allows authors to control under what circumstances (if any) a particular graphic element can become the target of mouse 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