【问题标题】:Click Triggers Event Listener That It Creates单击触发它创建的事件侦听器
【发布时间】:2022-01-28 05:53:26
【问题描述】:
在下面的示例中,为什么单击按钮不仅会触发添加到按钮的事件侦听器,还会触发添加到正文的事件侦听器?换句话说:为什么颜色会变成红色而不是绿色?以及如何防止这种情况发生?
$("button").on("click", function() {
// Change Color
$("body").css({
"background-color": "#3FE1B0"
});
// Add New Event Listener...
$("body").on("click", function() {
// ...Which Also Changes Color
$(this).css({
"background-color": "#FF4F5E"
});
});
});
/* Design Changes */
body {
height: 100vh;
margin: 0;
display: flex;
justify-content: center;
align-items: center;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0/jquery.min.js"></script>
<button>Click Me!</button>
【问题讨论】:
标签:
javascript
jquery
dom-events
【解决方案1】:
你的问题是event propagation。当用户使用您的原始代码单击按钮时会发生什么:
- 事件处理程序触发并将背景颜色更改为您指定的颜色 (#3FE1B0)
- 事件处理程序也被添加到正文中以将颜色更改为#FF4F5E
- 事件向上传播到其父元素,包括位于链末端的主体
- 因此主体上的事件处理程序运行(它只是刚刚添加的事实没有任何区别),因此颜色变为您不想要的颜色
解决方法很简单:使用事件的stopPropagation 方法阻止它向上传播:
$("button").on("click", function(event) {
// Change Color
$("body").css({
"background-color": "#3FE1B0"
});
// Add New Event Listener...
$("body").on("click", function() {
// ...Which Also Changes Color
$(this).css({
"background-color": "#FF4F5E"
});
});
event.stopPropagation();
});
/* Design Changes */
body {
height: 100vh;
margin: 0;
display: flex;
justify-content: center;
align-items: center;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0/jquery.min.js"></script>
<button>Click Me!</button>
【解决方案2】:
问题的根源之一是单击<body> 内的<button> 会触发<body> 元素和<button> 元素的单击事件。您需要使用event.stopPropagation() 来防止事件冒泡 DOM 树。
$("button").on("click", function(e) {
$("body").css({ "background-color": "#3FE1B0" });
e.stopPropagation();
});
$("body").on("click", function(e) {
$("body").css({ "background-color": "#FF4F5E" });
});
body {
height: 100vh;
margin: 0;
display: flex;
justify-content: center;
align-items: center;
}
<!DOCTYPE html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<title>Page Title</title>
</head>
<body>
<button>Click Me!</button>
</body>
</html>
【解决方案3】:
首先,您应该重新排列代码。
其次,使用stopPropagation 防止触发两个点击处理程序。
试试下面的例子:
$("body").on("click", function(e) {
$(this).css({
"background-color": "#FF4F5E"
});
});
$("button").on("click", function(e) {
e.stopPropagation()
$("body").css({
"background-color": "#3FE1B0"
});
});
/* Design Changes */
body {
height: 100vh;
margin: 0;
display: flex;
justify-content: center;
align-items: center;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0/jquery.min.js"></script>
<button>Click Me!</button>