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

时间:2016-01-23 18:00:00

标签: javascript radio-button addeventlistener dynamically-generated

我想为每个无线电输入点击附加一个事件监听器,以便我可以检索该无线电输入的值并将其指定为allQuestions数组中当前问题对象中新属性的值。

我不确定为什么我在choice.addEventListener工作时遇到困难。

我的HTML:

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

我的JavaScript:

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);

1 个答案:

答案 0 :(得分:4)

您正在尝试同时使用标记和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所做的事情。)

现在,说完了,你不需要每个单选按钮上的处理程序。相反,您可以使用<{1}}元素上的处理程序使用事件委派,然后在处理程序中使用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才能找到您感兴趣的元素(比如说&#39;对parentNode感兴趣,但点击位于div内;但是,span元素当然不能包含任何元素,所以这里很简单。

您可能想知道检查标签名称的原因。如果您将单选按钮与input元素相关联(通常是一种良好做法),可以将label 置于 input内或使用{{1 label上的{}}属性,当您点击for时,您会看到两次点击:标签本身上有一个,label上有第二个点击1}}标签与之相关。我们只对实际单选按钮上的那个感兴趣。

以上是代表团的一个简单示例:

&#13;
&#13;
label
&#13;
input
&#13;
&#13;
&#13;