EventListeners,在 JavaScript 中的另一个 EventListeners 中定义

EventListeners, which are defined in another EventListeners in JavaScript

提问人:MichaelLearner 提问时间:1/12/2023 更新时间:1/12/2023 访问量:58

问:

我想在单击后定义一个。EventListenerbutton

我设置了另一个,并希望孩子仅在触发父事件才收听。EventListenerEventListenerEventListenerclick event

代码片段:

const btn = document.querySelector(".btn")
btn.onclick = function() {
  console.log("PARENT")
  document.onclick = function() {
    console.log("CHILD")
  }
}
<button class="btn">Click</button>

当前行为:

父项和子项一起触发,即使在第一次单击按钮时也是如此。events

所以,即使在第一次点击我在控制台中看到,但我只想看到.button"PARENT" "CHILD""PARENT"

期望的行为:

孩子应该只有在点击元素后才能听。因此,我想在第一次单击仅在控制台中以及随后单击后看到:。EventListenerclick eventbuttonbutton"PARENT""PARENT" "CHILD"

为什么它以这种方式工作? 为什么 child 中定义的 , 会触发 parent 中定义的 , ,而 child 应该只在父项被触发时才开始监听eventEventListenereventEventListenerEventListenerclick eventevent

javascript html 事件 dom-events addeventlistener

评论

1赞 Đinh Carabus 1/12/2023
查看“事件冒泡”。首先执行 btn 事件处理程序并注册文档单击处理程序。然后,事件在 dom 上向上传播,直到到达文档。在那里,它将触发此时已经注册的文档 onclick 处理程序。

答:

0赞 ErickJFZ 1/12/2023 #1

const btn = document.querySelector(".btn")
btn.onclick = function() {
  console.log("PARENT");
  setTimeout(() => (
    document.onclick = function() {
      console.log("CHILD")
    }
  ), 0);      
}
<button class="btn">Click</button>

更多内容: 为什么 setTimeout(fn, 0) 有时有用?

1赞 KooiInc 1/12/2023 #2

该事件针对按钮进行处理 - 在该按钮分配了新的侦听器,然后它冒泡并处理新注册的处理程序。

无论如何,使用事件委派数据属性来保存按钮的单击状态可能更容易、更清晰。例如:

document.addEventListener(`click`, handle);

function handle(evt) {
  console.clear();
  if (evt.target.classList.contains(`btn`)) {
    evt.target.dataset.clicked = 1;
    return console.log(`.btn clicked`);
  }
  
  if (evt.target === document.documentElement) {
    if (!document.querySelector(`.btn`).dataset.clicked) {
      return true;
    }
     
    return console.log(`document clicked`);
  }
}
<button class="btn">Click</button>