【问题标题】:How do I attach eventListeners to dynamically generated radio buttons?如何附加事件侦听器以动态生成单选按钮?
【发布时间】:2020-07-08 22:03:55
【问题描述】:

我想为每个无线电输入点击附加一个事件侦听器,以便我可以检索该无线电输入的值并将其分配为 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);

【问题讨论】:

  • 您是否尝试在添加之前将事件处理程序添加到选项中?
  • @rmjoia,是的,但是如果我将choice.addEventListener 放在quiz.appendChild(choice); 之后,它仍然不起作用

标签: javascript radio-button addeventlistener dynamically-generated


【解决方案1】:

您正在尝试同时使用标记和 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 中的任何特殊字符(如 &lt;)都按字面意思处理(因为这是 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 inside 放在label 中,或者在for 上使用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);
}
&lt;div id="quiz"&gt;&lt;/div&gt;

【讨论】:

  • 谢谢!很有帮助!
猜你喜欢
  • 2012-11-11
  • 1970-01-01
  • 2023-03-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-07
  • 1970-01-01
相关资源
最近更新 更多