DOM Event.StopPropagation 到 child 没有效果

DOM Event.StopPropagation to child has no effect

我正在做一个关于事件的教程,但我坚持使用 Event.StopPropagation() 方法。在我的示例中,children 的冒泡效果似乎受到了影响。

StopPropagation的定义:

The stopPropagation() method prevents propagation of the same event from being called. Propagation means bubbling up to parent elements or capturing down to child elements.

一开始以为是浏览器的问题,其实不是。我找不到解决方案。

代码:

// Event Bubbling and Propagation
//  element.addEventListener( type, func, useCapture);

let m = document.getElementById('m');
let d = document.getElementById('d');
let p = document.getElementById('p');
let s = document.getElementById('s');   

let highlight = (ev)=>{
    //add CSS class "gold" to the clicked element
    ev.stopPropagation();
    let target = ev.currentTarget;
    target.className = 'gold';
    reset(target);
}

let reset = (_element)=>{
    setTimeout(()=>{
        _element.className = '';
    }, 2000);
}

d.addEventListener('click', (ev)=>{
    ev.stopImmediatePropagation();
    log('Hi I\'m a DIV');
});

[m,d,p,s].forEach((element)=>{
    element.addEventListener('click', highlight);
})
#m,#d,#p,#s{    
 border: 2px solid black; 
 padding: 15px;
 margin: 10px;
}
.gold{
    background-color: gold;
}
<main id="m"> m
        <div id="d"> d
            <p id="p"> p
                <span id="s"> s</span>
            </p>
        </div>
    </main>

这不是事件的问题,你想多了。

你的例子只是将背景颜色应用到顶部元素,由于 children 没有定义它,它应用它下面的顶部元素。

并且如果您删除 stopImmediatePropagation() 颜色将应用,因为定义是:执行第一个事件处理程序,并停止执行其余的事件处理程序,第一个只是 log().

在下面的示例中,如果您将背景颜色应用于 child 元素,您会发现它们将保持不变。它自己的颜色仅应用于单击的颜色。

这意味着 JS 事件本身没有向上冒泡到 parent 个元素或向下捕获。并且 class 仅在单击一个时添加。使用开发工具检查它或在每个元素上添加 DOM 更改事件侦听器。

您混淆了 CSS 样式与 JS 事件冒泡。

示例:

// Event Bubbling and Propagation
//  element.addEventListener( type, func, useCapture);

let m = document.getElementById('m');
let d = document.getElementById('d');
let p = document.getElementById('p');
let s = document.getElementById('s');
let log = console.log;

let highlight = (ev)=>{
    //add CSS class "gold" to the clicked element
    ev.stopPropagation();
    let target = ev.currentTarget;
    target.className = 'gold';
    reset(target);
}

let reset = (_element)=>{
    setTimeout(()=>{
        _element.className = '';
    }, 2000);
}

d.addEventListener('click', (ev)=>{
    //ev.stopImmediatePropagation();
    log('Hi I\'m a DIV');
});

[m,d,p,s].forEach((element)=>{
    element.addEventListener('click', highlight);
})
#m,#d,#p,#s{    
 border: 2px solid black; 
 padding: 15px;
 margin: 10px;
}

#d {
background-color: blue;
}

#s {
background-color: red;
}

.gold{
    background-color: gold !important;
}
<main id="m"> m
        <div id="d"> d
            <p id="p"> p
                <span id="s"> s</span>
            </p>
        </div>
    </main>

编辑:

在你的例子中 child 节点没有背景 属性 (rgba(0, 0, 0, 0)),这意味着你需要在点击时设置它,这样被点击元素的背景颜色就不会应用children.

在下面的代码中,您可以读取被单击元素的 parent 元素的 CSS 背景值,并读取其背景 属性。你把它应用到所有 children 的点击。

这将适用于您的示例。 如果 parent 是 transparent.

,您还可以确保将白色应用于元素

这里有一个 fiddle 可以玩: 但请确保您将 un-comment m (parent) 背景颜色查看副作用。您需要对此进行调整以满足您的生产需求

const style = getComputedStyle(target.parentNode);
const backgroundColor = style.backgroundColor;

console.clear();
console.log(backgroundColor);


[...target.children].forEach(el => {
if (backgroundColor==="rgba(0, 0, 0, 0)") {
  el.style.backgroundColor = "white";
  }else{
  el.style.backgroundColor = backgroundColor;}
})

// Event Bubbling and Propagation
//  element.addEventListener( type, func, useCapture);

let m = document.getElementById('m');
let d = document.getElementById('d');
let p = document.getElementById('p');
let s = document.getElementById('s');
let log = console.log;

let highlight = (ev)=>{
    //add CSS class "gold" to the clicked element
    ev.stopPropagation();
    let target = ev.currentTarget;
    target.className = 'gold';
    
    const style = getComputedStyle(target.parentNode);
    const backgroundColor = style.backgroundColor;
    
    console.clear();
    console.log(backgroundColor);
    
    
    [...target.children].forEach(el => {
    if (backgroundColor==="rgba(0, 0, 0, 0)") {
      el.style.backgroundColor = "white";
      }else{
      el.style.backgroundColor = backgroundColor;}
    })

    reset(target);
}

let reset = (_element)=>{
    setTimeout(()=>{
        _element.className = '';
    }, 2000);
}


[m,d,p,s].forEach((element)=>{
    element.addEventListener('click', highlight);
})
#m,#d,#p,#s{    
 border: 2px solid black; 
 padding: 15px;
 margin: 10px;
}


#m {
background-color: blue;
}


.gold{
    background-color: gold !important;
}
<main id="m"> m
        <div id="d"> d
            <p id="p"> p
                <span id="s"> s</span>
            </p>
        </div>
    </main>