【问题标题】:How do I make JS apply to dynamically added DOM elements?如何让 JS 应用于动态添加的 DOM 元素?
【发布时间】:2014-09-20 14:20:33
【问题描述】:

我正在向我的表单动态添加新元素,在用户单击“添加新元素”输入按钮时使用 JavaScript 克隆现有元素。这适用于第一个深度级别,但是当我尝试第二个级别时遇到问题:我单击“添加新字段”,除了“添加新子字段”按钮之外,还会出现一组新的表单字段。单击“添加新子字段”甚至不会调用它应该调用的函数,该函数应该在动态添加的字段中添加新字段。在另一个项目中,我记得我在将 JavaScript 应用于新的 DOM 元素时也遇到了麻烦,我认为这可能是问题所在。有办法吗?怎么样?

我的代码:(来自http://www.quirksmode.org/dom/domform.html的js)

    <form>
        <span id="writeroot_field"></span>
        <input type="button" id="more_fields" value="Add more fields">
        <input type="submit">
    </form>

    <div id="readroot_field" style="display:none">
        <span id='writeroot_subfield'></span>
        <input type='button' value='Add subfield' id='more_subfields'></input>
        <!-- more fields -->
    </div>

    <div id='readroot_subfield' style='display:none'>
        <!-- form fields -->
    </div>

    <script>
        // main fields
        var counter = 0;
            function moreFields() {
                counter++;
                var newFields = document.getElementById('readroot_field').cloneNode(true);
                newFields.id = '';
                newFields.style.display = 'block';
                var newField = newFields.childNodes;
                for (var i=0;i<newField.length;i++) {
                    var theName = newField[i].name
                    if (theName)
                        newField[i].name = theName + counter;
                }
                var insertHere = document.getElementById('writeroot_field');
                insertHere.parentNode.insertBefore(newFields,insertHere);
            }
        window.onload = moreFields; 
        document.getElementById('more_fields').onclick = moreFields;

        // subfields
        var counter2 = 0;
            function moreSubfields() {
                console.log('entering here? no?');
                counter2++;
                var newFields = document.getElementById('readroot_subfield').cloneNode(true);
                newFields.id = '';
                newFields.style.display = 'block';
                var newField = newFields.childNodes;
                for (var i=0;i<newField.length;i++) {
                    var theName = newField[i].name
                    if (theName)
                        newField[i].name = theName + counter2;
                }
                var insertHere = document.getElementById('writeroot_subfield');
                insertHere.parentNode.insertBefore(newFields,insertHere);
            }

        document.getElementById('more_subfields').onclick = moreSubfields;
    </script>

【问题讨论】:

  • 只为像$('body').on('click','#more_subfields', function() { etc })这样的body做点击事件
  • 如果你想让动态添加的元素有监听器,那么你需要添加监听器。您可以动态地执行此操作,在线添加侦听器并克隆元素,或使用事件委托。您的选择。
  • @Barmar——我不同意答案必然是事件委托。这是一种解决方案,不一定是 解决方案,也没有在问题中提及。
  • @Michael 他没有使用 jQuery。
  • @RobG 好的,我重新提出了这个问题。似乎这可能以前出现过,所以应该有一个更好的问题来复制它。

标签: javascript html forms dom interactive


【解决方案1】:

当使用 cloneNode() 已设置的事件处理程序时

element.onclick = function() { ... }

element.addEventListener("click", function() { ... })

不会被克隆(参见MDN: Node.cloneNode)。

解决您的问题的方法是在每次复制时为新节点设置一个事件处理程序:

<form>
    <span id="writeroot_field"></span>
    <input type="button" id="more_fields" value="Add more fields">
    <input type="submit">
</form>

<div id="readroot_field" style="display:none">
    <span id='writeroot_subfield'></span>
    <input type='button' value='Add subfield' id='more_subfields'></input>
    <!-- more fields -->
</div>

<div id='readroot_subfield' style='display:none'>
    <!-- form fields -->
</div>

<script>
    // main fields
    var counter = 0;
        function moreFields() {
            counter++;
            var newFields = document.getElementById('readroot_field').cloneNode(true);
            newFields.id = '';
            newFields.style.display = 'block';
            //set event handler
            newFields.onclick = moreFields;
            var newField = newFields.childNodes;
            for (var i=0;i<newField.length;i++) {
                var theName = newField[i].name
                if (theName)
                    newField[i].name = theName + counter;
            }
            var insertHere = document.getElementById('writeroot_field');
            insertHere.parentNode.insertBefore(newFields,insertHere);
        }
    window.onload = moreFields; 
    document.getElementById('more_fields').onclick = moreFields;

    // subfields
    var counter2 = 0;
        function moreSubfields() {
            console.log('entering here? no?');
            counter2++;
            var newFields = document.getElementById('readroot_subfield').cloneNode(true);
            newFields.id = '';
            newFields.style.display = 'block';
            //set event handler
            newFields.onclick = moreSubfields;
            var newField = newFields.childNodes;
            for (var i=0;i<newField.length;i++) {
                var theName = newField[i].name
                if (theName)
                    newField[i].name = theName + counter2;
            }
            var insertHere = document.getElementById('writeroot_subfield');
            insertHere.parentNode.insertBefore(newFields,insertHere);
        }

    document.getElementById('more_subfields').onclick = moreSubfields;
</script>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-05-24
    • 2021-09-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-18
    • 2017-07-19
    相关资源
    最近更新 更多