我有一个奇怪的问题,即两次单击事件被触发,我不知道为什么会发生。
JS Fiddle单击名称之一,以便触发切换按钮,如果您在label元素之外单击,则不会发生,实际上只会触发一次。
我将事件附加到所有带有'testit'类的元素上,当我记录元素时,我得到一个长度为1的节点列表,当我记录了foreach循环正在运行多少次时,它就会运行一次。
如果我删除Javascript,则不会附加任何事件。
// SELECTER DEN FEATURED JOKE
$sql = " SELECT t1.cat_id,
t1.cat_name,
t1.cat_parent,
t1.cat_type
FROM categories t1
ORDER BY t1.cat_parent,
t1.cat_name";
$stmt = $dbCon->prepare($sql);
$stmt->execute();
$count = $stmt->rowCount();
if ($count > 0) {
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
$orders = [];
foreach($rows as $row){
$cat_parent = $row['cat_parent'];
if($cat_parent == 0){
$orders[$row['cat_id']]['parent'] = [
'cat_id' => $row['cat_id'],
'cat_name' => $row['cat_name'],
'cat_parent' => $row['cat_parent'],
'cat_type' => $row['cat_type']
];
continue;
}
if ($cat_parent != 0) {
$orders[$cat_parent][] = [
'cat_id' => $row['cat_id'],
'cat_name' => $row['cat_name'],
'cat_parent' => $row['cat_parent'],
'cat_type' => $row['cat_type']
];
continue;
}
}
$filter_html = '<form id="filter__form" class="filter__form testit">';
$filter_html .= '<ul class="filter__ul main">';
foreach($orders as $order){
$cat_id = escape($order['parent']['cat_id']);
$para = escape($order['parent']['cat_id']);
$cat_name = escape($order['parent']['cat_name']);
$cat_parent = escape($order['parent']['cat_parent']);
$cat_type = escape($order['parent']['cat_type']);
$filter_html .= '<label class="filter__label parent" for="filter_'.$cat_id.'">';
$filter_html .= '<p class="noselect">'.$cat_name.'</p>';
$filter_html .= '<input id="filter_'.$cat_id.'" type="checkbox" value="'.$cat_id.'" name="cat['.$cat_id.']" class="cat_parent" data-show="cat_subs_'.$cat_id.'">';
$filter_html .= '<i></i>';
$filter_html .= '</label>';
}
$filter_html .= '<input type="hidden" name="CSRFToken" value="'.$_SESSION['CSRFToken'].'">';
$filter_html .= '</ul>';
$filter_html .= '</form>';
}
?>
<div class="filter__head">
<h3 class="">
Filter - Dashboard
</h3>
</div>
<?php
echo $filter_html;
?>
JavaScript
window.addEventListener("load", function (e) {
var testit = document.querySelectorAll('.testit');
console.log(testit);
testit.forEach(function(e){
console.log('TESTIT');
e.addEventListener('click', function(){
alert('Hello world');
});
});
});
因此,该事件运行两次,这在控制台中得到确认,或者在事件触发时通过发出警报来确认,该节点对象的长度为1,如果我对其进行控制台操作(如果删除Javascript也不会确认),则该对象也得到确认。附件,这是怎么回事?
如果我在echo $filter_html
的底部做一个带有一类testit的按钮,然后单击该按钮,它将仅触发一次,有什么区别,如何在一个特定元素中触发两次,并在一次触发一次,有什么区别?另一个,是同一事件吗?。
如果我附加了mouseup事件,则所有事件仅触发一次。
如果我注释掉标签元素,它将不会触发两次?为什么会这样?
CSS
.filter__head h3{
padding: 15px;
background-color: #eee;
text-align: start;
color: #4a4a4a;
}
.filter__form{
max-height: 70vh;
height: 600px;
overflow: auto;
}
.filter__form .filter__ul .filter__label{
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
border-bottom: 1px solid rgba(0,0,0,0.06);
padding: 15px 20px;
cursor: pointer;
}
.filter__form .filter__ul .filter__label:last-child {
border-bottom: 1px solid #BBB;
}
.filter__form .filter__ul .filter__label > input {
display: none;
}
.filter__form .filter__ul .filter__label i {
display: inline-block;
float: right;
padding: 2px;
width: 40px;
height: 20px;
border-radius: 13px;
vertical-align: middle;
transition: .25s .09s;
position: relative;
background: #d8d9db;
box-sizing: initial;
}
.filter__form .filter__ul .filter__label i:after {
content: " ";
display: block;
width: 20px;
height: 20px;
border-radius: 50%;
background: #fff;
position: absolute;
left: 2px;
transition: .25s;
}
.filter__form .filter__ul .filter__label > input:checked + i {
background: #4bd865;
}
.filter__form .filter__ul .filter__label > input:checked + i:after {
-webkit-transform: translateX(20px);
transform: translateX(20px);
}
.filter__form .filter__ul .filter__label:hover {
cursor: pointer;
}
答案 0 :(得分:1)
通过单击包装输入和其他元素的label
元素,触发表单上的第二个click事件。标签元素触发关联输入元素上的click事件。 MDN says:
“ 在单击
label
并将其与表单控件关联时,也会为关联的控件引发点击事件。”
防止单击标签的默认操作不是解决方案,因为这会阻止关联复选框的状态更改。一种解决方法是,在复选框的状态更改时,附加input
事件而不是click
来执行所需的操作。
如果有更多的输入要以表格的形式进行监听,则与使用这种类型的事件委托时一样,情况将变得更加复杂。在这种情况下,您必须检查事件是否确实是由您希望响应点击的元素触发的。
答案 1 :(得分:0)
发生的事情是,您将事件附加到表单本身,这是具有类testit
的唯一元素。
尝试将事件侦听器添加到输入中,然后使用 event object 标识每个输入:
var inputs = document.querySelectorAll('.cat_parent');
inputs.forEach(function(input) {
input.addEventListener('click', function(event) { // you need to pass the event
alert(event.currentTarget.id); // Now in the event object you have just the one that was clicked
});
});