You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaScript克隆div出现倍增问题求助(测验系统前端开发)

问题排查:点击添加按钮出现元素批量倍增的原因及修复

问题原因

你的代码存在几个核心问题:

  • 克隆元素后直接追加到原元素内部:比如duplicateQuestion把createTable克隆后又塞回自身,导致每次点击都会复制当前所有嵌套内容,形成指数级倍增。
  • 重复使用唯一ID:克隆后页面出现多个相同ID的元素,违反HTML规范,也会导致DOM操作逻辑混乱。
  • 额外小错误:HTML里<input type="text" name="question">后面多了个无效的</textarea>标签,需要删除。

修复后的完整代码

<div class="createContainer">
    <form method="post" action="">
        <!-- 所有问题的父容器 -->
        <div id="questions-container">
            <!-- 单个问题模板,用类代替id -->
            <div class="question-template">
                <div>
                    <label>Question:</label>
                    <input type="text" name="question[]">
                </div>
                <!-- 当前问题的选项父容器 -->
                <div class="options-container">
                    <!-- 单个选项模板 -->
                    <div class="option-template">
                        <label>Option:</label>
                        <input type="text" name="option[]" />
                        <input type="radio" name="isCorrect_0">
                    </div>
                </div>
                <button type="button" class="btn-copy add-option">New Answer</button>
            </div>
        </div>
        
        <button type="button" class="btn-copy add-question">New Question</button>
        <button type="submit">Create Quiz</button>
    </form>
</div>

<script>
    // 添加新问题
    document.querySelector('.add-question').addEventListener('click', function() {
        const questionsContainer = document.getElementById('questions-container');
        const template = document.querySelector('.question-template');
        const clone = template.cloneNode(true);
        
        // 给新问题的单选框设置唯一name,避免和其他问题冲突
        const questionIndex = questionsContainer.children.length;
        const radio = clone.querySelector('input[type="radio"]');
        radio.name = `isCorrect_${questionIndex}`;
        
        // 清空克隆元素里的输入框内容和单选框状态
        clone.querySelectorAll('input[type="text"]').forEach(input => input.value = '');
        clone.querySelector('input[type="radio"]').checked = false;
        
        // 把克隆的问题追加到父容器末尾
        questionsContainer.appendChild(clone);
    });

    // 用事件委托绑定"添加选项"按钮事件(兼容新克隆的按钮)
    document.addEventListener('click', function(e) {
        if(e.target.classList.contains('add-option')) {
            const optionsContainer = e.target.closest('.question-template').querySelector('.options-container');
            const template = optionsContainer.querySelector('.option-template');
            const clone = template.cloneNode(true);
            
            // 继承当前问题的单选框name,保证同一问题内选项互斥
            const radioName = template.querySelector('input[type="radio"]').name;
            clone.querySelector('input[type="radio"]').name = radioName;
            
            // 清空输入框和单选框状态
            clone.querySelector('input[type="text"]').value = '';
            clone.querySelector('input[type="radio"]').checked = false;
            
            // 追加到选项容器末尾
            optionsContainer.appendChild(clone);
        }
    });
</script>

关键改动说明

  1. 容器结构调整:
    • 新增questions-container和options-container作为父容器,避免嵌套克隆的问题。
    • 把原ID改为类作为模板标识,保证页面ID唯一。
  2. 克隆逻辑修正:
    • 克隆模板后追加到父容器末尾,每次仅新增一个元素,不会批量复制已有内容。
  3. 表单数据优化:
    • 输入框name改为数组格式(question[]、option[]),后端可直接接收所有问题/选项集合。
    • 给每个问题的单选框设置唯一name,确保同一问题内选项互斥,不同问题互不干扰。
  4. 事件处理优化:
    • 用事件委托绑定添加选项的事件,新克隆的按钮无需重新绑定即可触发。
  5. 用户体验优化:
    • 克隆后清空输入框内容和单选框选中状态,避免复制原内容。

内容的提问来源于stack exchange,提问作者pvl_needhelp

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 01:57:30