JavaScript 事件侦听器对单选按钮上的标签的行为不同
JavaScript event listener acts differently on label on radio button
我正在尝试将事件侦听器动态添加到 JavaScript 中的一组按钮。但是,只有在单选按钮中单击实际的圆形按钮而不是按钮的标签时,该函数才会正确触发。
function setupRadioBackground(someCard) {
someCard.querySelectorAll(".form-check-input").forEach((child) => {
console.log("initial test", someCard);
child.addEventListener("click", function() {
console.log(someCard);
shadeBackground(someCard, child);
})
})
}
当该函数最初运行时,它会正确显示要添加事件侦听器的卡片 initial test <card here>
。但是,当我在匿名事件侦听器函数中记录 someCard
时,我得到了不同的结果。如果我单击该标签,它会记录 添加了事件侦听器的第一个 someCard。但是,如果我单击圆形按钮,它会记录正确的卡片并且 shadeBackground
功能正常工作。
有没有办法让标签同样影响正确的卡片?
最小可重现示例
要重现该问题,请使用 按钮添加两张(或更多)卡片。单击第二张卡的无线电输入和标签。单击无线电输入将正确 select 它,而单击标签将 select 第一张卡的相应无线电输入。 (使用“整页”按钮,以更好地显示输出。)
const button = document.querySelector("#clickme");
let counter = 0;
button.addEventListener("click", function() {
const card = document.createElement("div");
card.className = "card";
card.id = `demoCard-${counter}`;
card.innerHTML = `<div class="card-body">
<h5 class="card-title">Card title</h5>
<div class="form-check">
<input class="form-check-input" type="radio" name="exampleRadios" id="exampleRadios1" value="option1" checked>
<label class="form-check-label" for="exampleRadios1">
Default radio
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="exampleRadios" id="exampleRadios2" value="option2">
<label class="form-check-label" for="exampleRadios2">
Second default radio
</label>
</div>
</div>`
document.querySelector(".output").appendChild(card);
document.querySelector(`#demoCard-${counter}`).querySelectorAll(".form-check").forEach((child) => {
child.addEventListener("change", function() {
console.log("you have clicked", child);
})
})
counter += 1;
})
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"
integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo"
crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css"
integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z" crossorigin="anonymous">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.0/umd/popper.min.js"
integrity="sha384-cs/chFZiN24E4KMATLdqdvsezGxaGsi4hLGOzlXwp5UZB1LY//20VyM2taTB4QvJ"
crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/js/bootstrap.min.js"
integrity="sha384-uefMccjFJAIv6A+rW+L4AHf99KvxDjWSu1z9VI8SKNVmz4sk7buKt/6v9KI65qnm"
crossorigin="anonymous"></script>
<div class="output">
<button id="clickme">Click Me</button>
</div>
您的代码中存在多个问题:
您在同一个表单上有多个具有相同 ID 的控件。使用以下代码更新卡片的内部 HTML,以便每张卡片的单选按钮具有不同的名称和 ID:
card.innerHTML = `<div class="form-check">
<input class="form-check-input" type="radio" name="exampleRadios${counter}" id="exampleRadios${counter}_1" value="option1" checked>
<label class="form-check-label" for="exampleRadios${counter}_1">
Default radio
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="exampleRadios${counter}" id="exampleRadios${counter}_2" value="option2">
<label class="form-check-label" for="exampleRadios${counter}_2">
Second default radio
</label>
</div>`
您想为特定元素添加事件侦听器,而不是在所有更改事件上一次又一次地添加。变化:
document.querySelector(`#demoCard-${counter}`).querySelectorAll(".form-check").forEach((child) => {
addEventListener("change", function() {
console.log("you have clicked", child);
})
})
至:
document.querySelector(`#demoCard-${counter}`).querySelectorAll(".form-check").forEach((child) => {
child.addEventListener("change", function() {
console.log("you have clicked", child);
})
})
这应该可以解决您的问题。
之后您的表单将按预期工作:
const button = document.querySelector("#clickme");
let counter = 0;
button.addEventListener("click", function() {
const card = document.createElement("div");
card.className = "card";
card.id = `demoCard-${counter}`;
card.innerHTML = `<div class="card-body">
<h5 class="card-title">Card title</h5>
<div class="form-check">
<input class="form-check-input" type="radio" name="exampleRadios${counter}" id="exampleRadios${counter}_1" value="option1" checked>
<label class="form-check-label" for="exampleRadios${counter}_1">
Default radio
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="exampleRadios${counter}" id="exampleRadios${counter}_2" value="option2">
<label class="form-check-label" for="exampleRadios${counter}_2">
Second default radio
</label>
</div>
</div>`
document.querySelector(".output").appendChild(card);
document.querySelector(`#demoCard-${counter}`).querySelectorAll(".form-check").forEach((child) => {
child.addEventListener("change", function() {
console.log("you have clicked", child);
});
});
counter += 1;
})
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z" crossorigin="anonymous">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.0/umd/popper.min.js" integrity="sha384-cs/chFZiN24E4KMATLdqdvsezGxaGsi4hLGOzlXwp5UZB1LY//20VyM2taTB4QvJ" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/js/bootstrap.min.js" integrity="sha384-uefMccjFJAIv6A+rW+L4AHf99KvxDjWSu1z9VI8SKNVmz4sk7buKt/6v9KI65qnm" crossorigin="anonymous"></script>
<div class="output">
<button id="clickme">Click Me</button>
</div>
主要问题是当您 运行:
时,您 re-using 与 id 相同
card.innerHTML = `<div class="card-body">
<h5 class="card-title">Card title</h5>
<div class="form-check">
<input class="form-check-input" type="radio" name="exampleRadios" id="exampleRadios1" value="option1" checked>
<label class="form-check-label" for="exampleRadios1">
Default radio
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="exampleRadios" id="exampleRadios2" value="option2">
<label class="form-check-label" for="exampleRadios2">
Second default radio
</label>
</div>
</div>`
每张新卡的收音机都将使用 id="exampleRadios1"
和 id="exampleRadios2"
。 id 应该是一个标识符,它标识单个元素。浏览器也做这个假设,所以当你用 for="exampleRadios1"
引用 id 时,它总是用 id="exampleRadios1"
.
引用第一个元素
您可以通过多种方式解决这个问题。最简单的方法是不分配 id 和 for,而是用 <label>
.[=19 包装 <input>
=]
card.innerHTML = `<div class="card-body">
<h5 class="card-title">Card title</h5>
<div class="form-check">
<label class="form-check-label">
<input class="form-check-input" type="radio" name="exampleRadios" value="option1" checked>
Default radio
</label>
</div>
<div class="form-check">
<label class="form-check-label">
<input class="form-check-input" type="radio" name="exampleRadios" value="option2">
Second default radio
</label>
</div>
</div>`
我正在尝试将事件侦听器动态添加到 JavaScript 中的一组按钮。但是,只有在单选按钮中单击实际的圆形按钮而不是按钮的标签时,该函数才会正确触发。
function setupRadioBackground(someCard) {
someCard.querySelectorAll(".form-check-input").forEach((child) => {
console.log("initial test", someCard);
child.addEventListener("click", function() {
console.log(someCard);
shadeBackground(someCard, child);
})
})
}
当该函数最初运行时,它会正确显示要添加事件侦听器的卡片 initial test <card here>
。但是,当我在匿名事件侦听器函数中记录 someCard
时,我得到了不同的结果。如果我单击该标签,它会记录 添加了事件侦听器的第一个 someCard。但是,如果我单击圆形按钮,它会记录正确的卡片并且 shadeBackground
功能正常工作。
有没有办法让标签同样影响正确的卡片?
最小可重现示例
要重现该问题,请使用 按钮添加两张(或更多)卡片。单击第二张卡的无线电输入和标签。单击无线电输入将正确 select 它,而单击标签将 select 第一张卡的相应无线电输入。 (使用“整页”按钮,以更好地显示输出。)
const button = document.querySelector("#clickme");
let counter = 0;
button.addEventListener("click", function() {
const card = document.createElement("div");
card.className = "card";
card.id = `demoCard-${counter}`;
card.innerHTML = `<div class="card-body">
<h5 class="card-title">Card title</h5>
<div class="form-check">
<input class="form-check-input" type="radio" name="exampleRadios" id="exampleRadios1" value="option1" checked>
<label class="form-check-label" for="exampleRadios1">
Default radio
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="exampleRadios" id="exampleRadios2" value="option2">
<label class="form-check-label" for="exampleRadios2">
Second default radio
</label>
</div>
</div>`
document.querySelector(".output").appendChild(card);
document.querySelector(`#demoCard-${counter}`).querySelectorAll(".form-check").forEach((child) => {
child.addEventListener("change", function() {
console.log("you have clicked", child);
})
})
counter += 1;
})
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"
integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo"
crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css"
integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z" crossorigin="anonymous">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.0/umd/popper.min.js"
integrity="sha384-cs/chFZiN24E4KMATLdqdvsezGxaGsi4hLGOzlXwp5UZB1LY//20VyM2taTB4QvJ"
crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/js/bootstrap.min.js"
integrity="sha384-uefMccjFJAIv6A+rW+L4AHf99KvxDjWSu1z9VI8SKNVmz4sk7buKt/6v9KI65qnm"
crossorigin="anonymous"></script>
<div class="output">
<button id="clickme">Click Me</button>
</div>
您的代码中存在多个问题:
您在同一个表单上有多个具有相同 ID 的控件。使用以下代码更新卡片的内部 HTML,以便每张卡片的单选按钮具有不同的名称和 ID:
card.innerHTML = `<div class="form-check"> <input class="form-check-input" type="radio" name="exampleRadios${counter}" id="exampleRadios${counter}_1" value="option1" checked> <label class="form-check-label" for="exampleRadios${counter}_1"> Default radio </label> </div> <div class="form-check"> <input class="form-check-input" type="radio" name="exampleRadios${counter}" id="exampleRadios${counter}_2" value="option2"> <label class="form-check-label" for="exampleRadios${counter}_2"> Second default radio </label> </div>`
您想为特定元素添加事件侦听器,而不是在所有更改事件上一次又一次地添加。变化:
document.querySelector(`#demoCard-${counter}`).querySelectorAll(".form-check").forEach((child) => { addEventListener("change", function() { console.log("you have clicked", child); }) })
至:
document.querySelector(`#demoCard-${counter}`).querySelectorAll(".form-check").forEach((child) => { child.addEventListener("change", function() { console.log("you have clicked", child); }) })
这应该可以解决您的问题。
之后您的表单将按预期工作:
const button = document.querySelector("#clickme");
let counter = 0;
button.addEventListener("click", function() {
const card = document.createElement("div");
card.className = "card";
card.id = `demoCard-${counter}`;
card.innerHTML = `<div class="card-body">
<h5 class="card-title">Card title</h5>
<div class="form-check">
<input class="form-check-input" type="radio" name="exampleRadios${counter}" id="exampleRadios${counter}_1" value="option1" checked>
<label class="form-check-label" for="exampleRadios${counter}_1">
Default radio
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="exampleRadios${counter}" id="exampleRadios${counter}_2" value="option2">
<label class="form-check-label" for="exampleRadios${counter}_2">
Second default radio
</label>
</div>
</div>`
document.querySelector(".output").appendChild(card);
document.querySelector(`#demoCard-${counter}`).querySelectorAll(".form-check").forEach((child) => {
child.addEventListener("change", function() {
console.log("you have clicked", child);
});
});
counter += 1;
})
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z" crossorigin="anonymous">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.0/umd/popper.min.js" integrity="sha384-cs/chFZiN24E4KMATLdqdvsezGxaGsi4hLGOzlXwp5UZB1LY//20VyM2taTB4QvJ" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/js/bootstrap.min.js" integrity="sha384-uefMccjFJAIv6A+rW+L4AHf99KvxDjWSu1z9VI8SKNVmz4sk7buKt/6v9KI65qnm" crossorigin="anonymous"></script>
<div class="output">
<button id="clickme">Click Me</button>
</div>
主要问题是当您 运行:
时,您 re-using 与 id 相同card.innerHTML = `<div class="card-body"> <h5 class="card-title">Card title</h5> <div class="form-check"> <input class="form-check-input" type="radio" name="exampleRadios" id="exampleRadios1" value="option1" checked> <label class="form-check-label" for="exampleRadios1"> Default radio </label> </div> <div class="form-check"> <input class="form-check-input" type="radio" name="exampleRadios" id="exampleRadios2" value="option2"> <label class="form-check-label" for="exampleRadios2"> Second default radio </label> </div> </div>`
每张新卡的收音机都将使用 id="exampleRadios1"
和 id="exampleRadios2"
。 id 应该是一个标识符,它标识单个元素。浏览器也做这个假设,所以当你用 for="exampleRadios1"
引用 id 时,它总是用 id="exampleRadios1"
.
您可以通过多种方式解决这个问题。最简单的方法是不分配 id 和 for,而是用 <label>
.[=19 包装 <input>
=]
card.innerHTML = `<div class="card-body">
<h5 class="card-title">Card title</h5>
<div class="form-check">
<label class="form-check-label">
<input class="form-check-input" type="radio" name="exampleRadios" value="option1" checked>
Default radio
</label>
</div>
<div class="form-check">
<label class="form-check-label">
<input class="form-check-input" type="radio" name="exampleRadios" value="option2">
Second default radio
</label>
</div>
</div>`