繁体   English   中英

如何将 eventListeners 附加到动态生成的单选按钮?

[英]How do I attach eventListeners to dynamically generated radio buttons?

我想为每个单选输入点击附加一个事件侦听器,以便我可以检索该单选输入的值并将其分配为 allQuestions 数组中当前问题对象中的新属性的值。

我不确定为什么我很难让choice.addEventListener工作。

我的HTML:

<div id="quiz"></div>
<button id="button">Next</button>

我的脚本:

var allQuestions = [{question: "What is the capital of the Czech Republic?", 
                choices: ["Skopje", "Budapest", "Prague", "Bucharest"], 
                correctAnswer: 2},

                {question: "When was the Declaration of Independence signed?",
                choices: ["1492", "1776", "1812", "1791"],
                correctAnswer: 1}];

var quiz = document.getElementById("quiz");
var index = -1;

var next = function() {
    index += 1;
    quiz.innerHTML = "";
    for (var i = 0; i < allQuestions[index]['choices'].length; i++) {
        var choice = document.createElement('input');
        choice.type = 'radio';
        choice.name = 'choices';
        choice.value = i;
        choice.addEventListener('click', function() {
            alert('hi');
        });

        quiz.appendChild(choice);
        quiz.innerHTML += allQuestions[index]['choices'][i] + '<br>';
    }
};

var button = document.getElementById('button');
button.addEventListener('click', next);

您正在尝试同时使用标记和 DOM 元素。 这是主要问题:

quiz.appendChild(choice);
quiz.innerHTML += allQuestions[index]['choices'][i] + '<br>';

第一行将带有附加事件处理程序的 DOM 元素附加到quiz元素。 第二行将quiz的内容转换为 HTML 字符串,向该字符串附加一些进一步的文本(标记),然后解析该 HTML 并用解析的结果替换quiz的内容。 这会清除 HTML 中未表示的所有内容,包括动态添加的事件处理程序。

解决方案是不执行innerHTML +=... ,这几乎总是一个坏主意。 在这种特殊情况下,您可以这样做:

quiz.appendChild(choice);
quiz.appendChild(document.createTextNode(allQuestions[index]['choices'][i]));
quiz.appendChild(document.createElement('br'));

...这还有一个优点,即 HTML 中的任何特殊字符(如< )都按字面意思处理(因为这就是createTextNode所做的)。


现在,话虽如此,您不需要每个单选按钮上的处理程序。 相反,您可以通过在quiz元素上使用处理程序来使用事件委托,然后在处理程序中使用e.target来了解单击了哪个单选按钮:

quiz.addEventListener("click", function(e) {
    if (e.target.tagName.toUpperCase() === "INPUT") {
        var value = e.target.value; // The value of the clicked radio button
    }
});

这样,您就不必担心动态添加处理程序; 只需执行一次,在已知quiz元素存在之后,您可以根据需要更新其内容,而不必担心将处理程序附加到其中的单选按钮。

一般来说,要进行事件委托,您通常必须从e.target开始循环并转到其parentNode以找到您感兴趣的元素(假设您对div感兴趣,但点击是在span上在里面); 但是当然, input元素里面不能有任何元素,所以这里很简单。

您可能想知道为什么要检查标签名称。 如果将单选按钮与label元素相关联(这通常是一种好的做法),无论是通过将input放在label内还是在标签上使用for属性,当您单击label时,您将看到两次点击:一次在label上本身,第二个在标签相关的input上。 我们只对实际单选按钮上的那个感兴趣。

这是上面委托的一个简单示例:

 var quiz = document.getElementById("quiz"); quiz.addEventListener("click", function(e) { if (e.target.tagName.toUpperCase() === "INPUT") { var value = e.target.value; // The value of the clicked radio button console.log("The value of that radio button is " + value); } }); for (var n = 0; n < 5; ++n) { var div = document.createElement("div"); div.innerHTML = '<label><input type="radio" value="' + n + '" name="answer"> Radio ' + n + '</label>'; quiz.appendChild(div); }
 <div id="quiz"></div>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM