【问题标题】:how to bind dynamically created button click events to dynamically created input in javascript?如何将动态创建的按钮单击事件绑定到javascript中动态创建的输入?
【发布时间】:2019-10-14 18:23:27
【问题描述】:

我对 javascripts 非常陌生,并试图创建一个动态 html 表单,其中有多个按钮,每个按钮单击映射到相应的表单输入。这是我的代码:

<html>
<head>
    <title>Create Group</title>
    <script src="/js/jquery-3.4.1.min.js"></script>

    <script>

        $(document).ready(function(){

            $("#generate_form").click(function(){
            var number = document.getElementById("number_of_groups").value;
            var container = document.getElementById("container");
            while (container.hasChildNodes()) {
                container.removeChild(container.lastChild);
            }
            var i;
            for (i=1;i<=number;i++){
                var p = document.createElement("p");
                var node = document.createTextNode("group " + i + " :");
                p.appendChild(node);
                container.appendChild(p);
                var input = document.createElement("input");
                input.type = "text";
                var thisID = 'group_'+i;
                input.id = thisID;
                input.name=thisID;
                container.appendChild(input);
                var button = document.createElement("button");
                button.id = "button_"+i;
                button.type = "button";
                container.appendChild(button);
                button.onclick = function(){ document.getElementById(thisID).value = "hello world";};
                var buttonLabel = document.createTextNode("Generate");
                button.appendChild(buttonLabel);
                container.appendChild(document.createElement("br"));
            }
           })
        });
    </script>
</head>
<body>
    <h2>Create some group(s)</h2>
    <br>
    Create <input type="text" id="number_of_groups" name="number_of_groups" value="1"> group(s).
    <button id="generate_form" type="button">GO</button>
    <div id="container"/>

</body>
</html>`

因此,用户将输入要创建的组数并单击“开始”按钮,然后代码应使用用户选择的数字动态生成表单。每组表单都包括一个输入文本框和一个“生成”按钮。单击按钮时,输入文本框将显示“hello world”。但是,无论我单击哪个“生成”按钮,“hello world”都只会显示在最后一个输入文本框中。于是我把按钮的onclick函数改成了:

button.onclick = function(){ alert(thisID);};

然后我发现thisID 始终是最后一个输入文本框的 id,无论我单击哪个“生成”按钮。我猜这是因为在脚本完成之前,当“thisID”始终是其最新值时,点击事件的绑定才会发生。

有人可以帮我实现我想要的功能吗?非常感谢!

【问题讨论】:

  • 每个人都不要使用var,而是尝试使用let,看看是否能解决您的问题。 IE。 let thisID = 'group_'+i;
  • 非常感谢!这实际上解决了问题。我去看看letvar的区别。
  • 再次感谢!这是非常有用的信息。

标签: javascript html dom


【解决方案1】:

您需要将 for 循环中的代码包装在一个单独的函数中,将 i 的值作为参数传入。这将创建一个闭包,为您的代码创建一个新的执行范围。否则发生的事情是你的 var 被提升了,并且不是 for 循环的每次迭代所独有的,所以你的 DOM 只反映它被分配的最后一个值。

for (i=1;i<=number;i++){
  (function (i) {
    var p = document.createElement("p");
    var node = document.createTextNode("group " + i + " :");
    p.appendChild(node);
    container.appendChild(p);
    var input = document.createElement("input");
    input.type = "text";
    var thisID = 'group_'+i;
    input.id = thisID;
    input.name=thisID;
    container.appendChild(input);
    var button = document.createElement("button");
    button.id = "button_"+i;
    button.type = "button";
    container.appendChild(button);
    button.onclick = function(){ document.getElementById(thisID).value = "hello world";};
    var buttonLabel = document.createTextNode("Generate");
    button.appendChild(buttonLabel);
    container.appendChild(document.createElement("br"));
  })(i);
}

您可以在此处查看有关闭包的文章: https://medium.com/javascript-scene/master-the-javascript-interview-what-is-a-closure-b2f0d2152b36

编辑:正如您的一位评论者所提到的,您还可以将变量设置为“让”以达到类似的效果。这是因为 let 将变量范围限定为当前代码块,而不是提升到函数的范围,因此每个 for 循环迭代都有一个私有的 let 变量。不过,仍然建议您充分了解闭包及其工作原理。

【讨论】:

    【解决方案2】:

    由于您已经在使用 JQuery,您可以减少一些逻辑。 让我知道这是否有帮助-

    <html>
        <head>
            <title>Create Group</title>
        </head>
        <script src="/js/jquery-3.4.1.min.js"></script>
        <script>
            $(document).ready(()=>{
    
            var txtGroup='<input type="text" id="txt_group_{0}" value="">';
            var btnGroup='<button id="btn_group_{0}" type="button">Click Me</button>';
            var container=$('#container');
    
            $('#generate_form').click((e)=>{
                var groupCount=parseInt($('#number_of_groups').val());
                var idToStart=$('#container').children('div').length+1;
                for(let i=idToStart;i< idToStart+groupCount;i++){
                    var divGroup=`<div id="div_group_${i}">`+
                    txtGroup.replace('{0}',i)+
                    btnGroup.replace('{0}',i)+`</div>`;
    
                    container.append(divGroup);
                    $('#btn_group_'+i).on('click',(e)=>{
                        console.log('#txt_group_'+i);
                        $('#txt_group_'+i).val('Hello World');
                    });
                }
    
            });
    
        });
        </script>
        <body>
            <h2></h2>
            <br>
            Create <input type="text" id="number_of_groups" name="number_of_groups" value="1"> group(s).
            <button id="generate_form" type="button">GO</button>
            <div id="container"></div>
        </body>
        </html>
    

    【讨论】:

    • 非常感谢!这打开了我编写 javascripts 的眼界。我仍然不明白 jquery 和 javascripts 之间的区别。会做一些阅读。
    • 乐于助人。我相信你会得到大量关于 Javascript 和 JQuery 的信息 :)。简而言之,JQuery 是一个 javascript 库,我们使用 JS 库来实现比普通 JS 更简单(更少的代码行)的功能。然而,为了让 Web 开发人员自信,了解 vanilla JS 很重要,您可以了解 JQuery 在幕后所做的工作。
    猜你喜欢
    • 2011-09-05
    • 1970-01-01
    • 2014-02-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多