通过Javascript将事件监听器附加到单选按钮

23

我有几个同名的单选按钮,就像这样:

<form name="formA">
<input type="radio" name="myradio" value="A"/>
<input type="radio" name="myradio" value="B"/>
<input type="radio" name="myradio" value="C"/>
<input type="radio" name="myradio" value="D"/>
</form>

现在我需要通过JavaScript为所有单选按钮添加事件监听器。 如果以下伪代码有误,请告诉我如何更正 -

var radios = document.forms["formA"].elements["myradio"];
  for(radio in radios) {
    radio.onclick = function() {
        alert(radio.value);
    }
}
8个回答

23

在JavaScript中的for in循环中,返回的是对象的键而不是值。为了让for in循环正常工作,假设您没有向数组添加自定义属性,则应该使用以下方式:

for(radio in radios) {
    radios[radio].onclick = function() {
        alert(this.value);
    }
}

为了避免意外包含自定义添加的可枚举属性,您应该始终使用常规的for循环来循环数组:

var radios = document.forms["formA"].elements["myradio"];
for(var i = 0, max = radios.length; i < max; i++) {
    radios[i].onclick = function() {
        alert(this.value);
    }
}

为什么你应该“总是使用常规for循环来遍历数组”? - ojrask
1
@ojrask - 这是一个旧的回答,但基本上是自定义添加属性,如果添加了,就可以进行迭代。但当然,现在有了ES6,您可以使用for of循环与数组或任何可迭代对象一起使用。 - Adam Rackis
1
啊,是的,我明白了。没想到这一点。也许可以编辑答案来详细解释一下? :) - ojrask

14
另一种选择是使用委托处理程序将多个元素附加到单个事件侦听器,可以使用委托处理程序
您可以将父侦听器附加到document或任何适当的父节点。 然后,您可以使用Element.matches() API或event.target上的任何内容检查事件是否由适当的目标引发。
document.getElementById("languages").addEventListener('click', function (event) {
    if (event.target && event.target.matches("input[type='radio']")) {
        // do something here ...
    }
});

这大致相当于以下使用.on()提供委派的jQuery语法

$("#languages").on("click", "input[type='radio']", function(event) {
    // do something here ...
});

如果您想扩展EventTarget.addEventListener()原型,可以使用自己的方法进行包装:

window.EventTarget.prototype.addDelegatedListener = function(type, delegateSelector, listener) {
    this.addEventListener(type, function (event) {
        if (event.target && event.target.matches(delegateSelector)) {
            listener.call(event.target, event)
        }
    });
}

然后像这样使用:

document.addDelegatedListener("click", "input[type='radio']", function(event) {
    // do something here ...
});

在 Stack Snippets 中的演示

// example 1 - regular add event listener
document.getElementById("languages").addEventListener('click', function (event) {
    if ( event.target && event.target.matches("input[type='radio']") ) {
        console.log(event.target.value)
    }
});

// example 2 - reusable delegated listener
window.EventTarget.prototype.addDelegatedListener = function(type, delegateSelector, listener) {
    this.addEventListener(type, function (event) {
        if (event.target && event.target.matches(delegateSelector)) {
            listener.call(event.target, event)
        }
    });
}

let parent = document.getElementById("weekdays")
parent.addDelegatedListener("click", "input[type='radio']", function(event) {
    console.log(this.value)
});
h3 {
    margin-top: 20px;
    margin-bottom: 10px;
    font-size: 1.1em;
}
code {
    background: #e9e9e9;
    padding: 1px 4px;
    border-radius: 3px;
}
label input {
    vertical-align: text-top;
}
<h3>Languages <code>addEventListener</code> + <code>Element.matches</code></h3>
<div id="languages">
  <label><input type="radio" name="languages" value="HTML"> HTML </label>
  <label><input type="radio" name="languages" value="JS"> JS </label>
  <label><input type="radio" name="languages" value="CSS"> CSS </label>
</div>

<h3>Weekdays <code>EventTarget.prototype.addDelegatedListener</code></h3>
<div id="weekdays">
  <label><input type="radio" name="days" value="Mon"> Mon </label>
  <label><input type="radio" name="days" value="Tue"> Tue </label>
  <label><input type="radio" name="days" value="Wed"> Wed </label>
</div>


我同意建议使用事件委托模式,但我不同意用自定义方法扩展本地内置功能,出于与this blog相同的原因,它建议你不应该这样做。也许只是创建一个函数来创建委托侦听器而不将其添加到EventTarget.prototype中会更具未来性,或者创建一个包装器对象以首先进行扩展,例如当您 $()时jQuery返回什么。 - ADJenks

8
你可以添加一个单一的监听器来监听所有单选按钮,而不是个别监听器。 使用jquery,你可以这样做
$(document).ready(function(){
    $('input[type=radio]').click(function(){
        alert(this.value);
    });
});

演示

只针对id为formA的表单中的单选框进行操作。

 $(document).ready(function(){
        $('#formA input[type=radio]').click(function(){
            alert(this.value);
        });
    });

仅适用于具有id myradio的收音机。

$(document).ready(function(){
    $('input[type=radio]').click(function(){
        if (this.id == "myradio")
            alert(this.value);
    });
});

Demo


3
  1. 我需要纯 JavaScript 代码。
  2. 我想要将事件监听器附加到那些 name 属性设置为 "myradio" 的单选框(请考虑)。但是我认为上述代码会将函数附加到整个文档中的所有单选框。:(
- Acn
@BigFatPig,您可以将其仅附加到特定表单中的收音机,甚至是具有特定ID的收音机。 - Ayush

6
一个不错的开始,但是不要像这样使用for..in,因为它会遍历所有可枚举属性,并且你没有检查它们是否都代表元素。
更好的方法是使用索引:
for (var i=0, iLen=radios.length; i<iLen; i++) {
  radios[i].onclick = function() {...};
} 

2

试试这个:

var radioButtonSection = document.getElementsByName('eazi_auto_loan_option');

for (var i = 0; i < radioButtonSection.length; i++) {
        radioButtonSection[i].onclick = function() {
            console.log(this.value);
        }
    }

2
for(var property in object) { ... } 

for...in语句被用来循环遍历对象并查找属性。 对于数组,您可以使用普通的for循环。

for(var i=0; i< radios.length; i++) {
     var radio = radios[i];
     ....
} 

0
最优雅的解决方案:
将监听器附加到FORM元素。然后,事件将从单选按钮冒泡到表单。
以下代码假定您在表单中只有单选按钮,就像问题中的示例一样。
如果有其他输入元素,请将单选组包含在span中,然后将监听器附加到span。
let myForm = document.forms["formA"];
myForm.onchange = evt => console.log("Radio Checked:", evt.target.value);

这不会触发,如果用JavaScript以编程方式更改了单选按钮的选中状态。 - stevecomrie

0
for (let elem of document.querySelectorAll('input[type="radio"][name="myradio"]')) {
    elem.addEventListener("input", (event) => {  
        console.log(event.target.value);
    });
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接