单击事件不适用于内部标记元素
click event not working on inner tag elements
这是我正在使用的标记
<div class="checkout-row__form-column__billing">
<div class="checkout-row__form-column__billing__title billing-collapse collapse-btn">
<div class="checkout-row__form-column__billing__title__arrow">
<i class="fa fa-chevron-right" aria-hidden="true"></i>
</div>
<h2>1. Billing Details</h2>
</div>
<div class="checkout-row__form-column__shipping__content shipping-collapse-content collapse-target"></div>
<div class="checkout-row__form-column__shipping">
<div class="checkout-row__form-column__shipping__title shipping-collapse collapse-btn">
<div class="checkout-row__form-column__shipping__title__arrow">
<i class="fa fa-chevron-right" aria-hidden="true"></i>
</div>
<h2>2. Shipping Details</h2>
</div>
<div class="checkout-row__form-column__shipping__content shipping-collapse-content collapse-target"></div>
所有这些标记都包含在 div
中,class 为 checkout-row__form-column
。
所以,我正在抓取父包装器,单击我将目标与 .collapse-btn
匹配。然后我 class 切换 .collapse-target
的兄弟姐妹。效果很好,除了问题,我无法通过。如果我点击内部元素,事件不会发生。
这是我的js
parent = document.querySelector('.checkout-row__form-column');
parent.addEventListener('click', (e)=>{
if (e.target.matches('.collapse-btn')) {
e.stopPropagation();
e.target.nextElementSibling.classList.toggle('hide');
}
});
使用这些代码,如果我不单击 i
元素或 h2
,我可以切换 classes。如果我单击 e.target
.
中的任意位置,我该如何编写我的 JavaScript 事件将被触发
非常感谢战友们的帮助。
您的代码仅检查 event.target
是否为 .collapse-btn
元素。您还需要检查单击的元素是否是 .collapse-btn
元素的后代元素。
为了达到预期的结果,您可以使用这两个条件来检查 event.target
是否是 .collapse-btn
或其任何后代。要检查后代元素,请使用通用选择器 *
.
parent.addEventListener('click', (e) => {
if (
e.target.matches('.collapse-btn') ||
e.target.matches('.collapse-btn *')
) {
// code
}
});
演示
以下片段显示了一个示例:
const parent = document.querySelector('.container');
parent.addEventListener('click', e => {
if (
e.target.matches('.collapse-btn') ||
e.target.matches('.collapse-btn *')
) {
parent.classList.toggle('active');
}
});
.container {
background: #eee;
width: 120px;
height: 120px;
}
.container.active {
border: 2px solid;
}
.collapse-btn {
background: #999;
padding: 10px;
}
.collapse-btn span {
background: #fc3;
font-size: 1.3rem;
cursor: pointer;
}
<div class="container">
<div class="collapse-btn">
<span>Click</span>
</div>
</div>
您也可以将选择器放在一个数组中,然后使用 .some()
方法检查 event.target
是否匹配数组中的任何一个选择器。
const selectors = ['.collapse-btn', '.collapse-btn *'];
parent.addEventListener('click', e => {
if (selectors.some(s => e.target.matches(s))) {
// code
}
});
演示
以下片段显示了一个示例:
const parent = document.querySelector('.container');
parent.addEventListener('click', e => {
const selectors = ['.collapse-btn', '.collapse-btn *'];
if (selectors.some(s => e.target.matches(s))) {
parent.classList.toggle('active');
}
});
.container {
background: #eee;
width: 120px;
height: 120px;
}
.container.active {
border: 2px solid;
}
.collapse-btn {
background: #999;
padding: 10px;
}
.collapse-btn span {
background: #fc3;
font-size: 1.3rem;
cursor: pointer;
}
<div class="container">
<div class="collapse-btn">
<span>Click</span>
</div>
</div>
备选方案
不使用 .matches()
方法,而是使用 Element.closest()
and Node.contains()
方法的组合来检查 event.target
是 .collapse-btn
元素还是 .collapse-btn
元素的子元素.collapse-btn
元素。
为此,您需要执行两个步骤:
您首先需要获取 .collapse-btn
,它是 event.target
的最近祖先。
之后,您需要检查 event.target
是否是在步骤 1 中选择的按钮的后代。
代码:
parent.addEventListener('click', (e) => {
const targetCollapseBtn = e.target.closest('.collapse-btn');
if (targetCollapseBtn && targetCollapseBtn.contains(e.target)) {
...
}
});
如果event.target
是.collapse-btn
本身,那么
e.target.closest('.collpase-btn')
将 return e.target
,即 .collapse-btn
和
targetCollapseBtn.contains(e.target)
也将 return 为真,因为 .contains()
方法 return 为真,即使作为参数传递给它的节点与 .contains()
方法被调用。
因此,以这种方式使用 .closest()
和 .contains()
方法涵盖了两种用例,即单击 .collapse-btn
或单击其任何后代元素时。
演示
以下代码片段显示了一个简单示例:
const parent = document.querySelector('.container');
parent.addEventListener('click', e => {
const targetCollapseBtn = e.target.closest('.collapse-btn');
if (targetCollapseBtn && targetCollapseBtn.contains(e.target)) {
parent.classList.toggle('active');
}
});
.container {
background: #eee;
width: 120px;
height: 120px;
}
.container.active {
border: 2px solid;
}
.collapse-btn {
background: #999;
padding: 10px;
}
.collapse-btn span {
background: #fc3;
font-size: 1.3rem;
cursor: pointer;
}
<div class="container">
<div class="collapse-btn">
<span>Click</span>
</div>
</div>
这是我正在使用的标记
<div class="checkout-row__form-column__billing">
<div class="checkout-row__form-column__billing__title billing-collapse collapse-btn">
<div class="checkout-row__form-column__billing__title__arrow">
<i class="fa fa-chevron-right" aria-hidden="true"></i>
</div>
<h2>1. Billing Details</h2>
</div>
<div class="checkout-row__form-column__shipping__content shipping-collapse-content collapse-target"></div>
<div class="checkout-row__form-column__shipping">
<div class="checkout-row__form-column__shipping__title shipping-collapse collapse-btn">
<div class="checkout-row__form-column__shipping__title__arrow">
<i class="fa fa-chevron-right" aria-hidden="true"></i>
</div>
<h2>2. Shipping Details</h2>
</div>
<div class="checkout-row__form-column__shipping__content shipping-collapse-content collapse-target"></div>
所有这些标记都包含在 div
中,class 为 checkout-row__form-column
。
所以,我正在抓取父包装器,单击我将目标与 .collapse-btn
匹配。然后我 class 切换 .collapse-target
的兄弟姐妹。效果很好,除了问题,我无法通过。如果我点击内部元素,事件不会发生。
这是我的js
parent = document.querySelector('.checkout-row__form-column');
parent.addEventListener('click', (e)=>{
if (e.target.matches('.collapse-btn')) {
e.stopPropagation();
e.target.nextElementSibling.classList.toggle('hide');
}
});
使用这些代码,如果我不单击 i
元素或 h2
,我可以切换 classes。如果我单击 e.target
.
非常感谢战友们的帮助。
您的代码仅检查 event.target
是否为 .collapse-btn
元素。您还需要检查单击的元素是否是 .collapse-btn
元素的后代元素。
为了达到预期的结果,您可以使用这两个条件来检查 event.target
是否是 .collapse-btn
或其任何后代。要检查后代元素,请使用通用选择器 *
.
parent.addEventListener('click', (e) => {
if (
e.target.matches('.collapse-btn') ||
e.target.matches('.collapse-btn *')
) {
// code
}
});
演示
以下片段显示了一个示例:
const parent = document.querySelector('.container');
parent.addEventListener('click', e => {
if (
e.target.matches('.collapse-btn') ||
e.target.matches('.collapse-btn *')
) {
parent.classList.toggle('active');
}
});
.container {
background: #eee;
width: 120px;
height: 120px;
}
.container.active {
border: 2px solid;
}
.collapse-btn {
background: #999;
padding: 10px;
}
.collapse-btn span {
background: #fc3;
font-size: 1.3rem;
cursor: pointer;
}
<div class="container">
<div class="collapse-btn">
<span>Click</span>
</div>
</div>
您也可以将选择器放在一个数组中,然后使用 .some()
方法检查 event.target
是否匹配数组中的任何一个选择器。
const selectors = ['.collapse-btn', '.collapse-btn *'];
parent.addEventListener('click', e => {
if (selectors.some(s => e.target.matches(s))) {
// code
}
});
演示
以下片段显示了一个示例:
const parent = document.querySelector('.container');
parent.addEventListener('click', e => {
const selectors = ['.collapse-btn', '.collapse-btn *'];
if (selectors.some(s => e.target.matches(s))) {
parent.classList.toggle('active');
}
});
.container {
background: #eee;
width: 120px;
height: 120px;
}
.container.active {
border: 2px solid;
}
.collapse-btn {
background: #999;
padding: 10px;
}
.collapse-btn span {
background: #fc3;
font-size: 1.3rem;
cursor: pointer;
}
<div class="container">
<div class="collapse-btn">
<span>Click</span>
</div>
</div>
备选方案
不使用 .matches()
方法,而是使用 Element.closest()
and Node.contains()
方法的组合来检查 event.target
是 .collapse-btn
元素还是 .collapse-btn
元素的子元素.collapse-btn
元素。
为此,您需要执行两个步骤:
您首先需要获取
.collapse-btn
,它是event.target
的最近祖先。之后,您需要检查
event.target
是否是在步骤 1 中选择的按钮的后代。
代码:
parent.addEventListener('click', (e) => {
const targetCollapseBtn = e.target.closest('.collapse-btn');
if (targetCollapseBtn && targetCollapseBtn.contains(e.target)) {
...
}
});
如果event.target
是.collapse-btn
本身,那么
e.target.closest('.collpase-btn')
将 return e.target
,即 .collapse-btn
和
targetCollapseBtn.contains(e.target)
也将 return 为真,因为 .contains()
方法 return 为真,即使作为参数传递给它的节点与 .contains()
方法被调用。
因此,以这种方式使用 .closest()
和 .contains()
方法涵盖了两种用例,即单击 .collapse-btn
或单击其任何后代元素时。
演示
以下代码片段显示了一个简单示例:
const parent = document.querySelector('.container');
parent.addEventListener('click', e => {
const targetCollapseBtn = e.target.closest('.collapse-btn');
if (targetCollapseBtn && targetCollapseBtn.contains(e.target)) {
parent.classList.toggle('active');
}
});
.container {
background: #eee;
width: 120px;
height: 120px;
}
.container.active {
border: 2px solid;
}
.collapse-btn {
background: #999;
padding: 10px;
}
.collapse-btn span {
background: #fc3;
font-size: 1.3rem;
cursor: pointer;
}
<div class="container">
<div class="collapse-btn">
<span>Click</span>
</div>
</div>