在开发问卷、考试或报名系统时,经常遇到题目数量由用户自行决定的情况。如果提前写死页面结构,既无法满足灵活需求,也会让后期维护变得困难。使用JavaScript在运行时动态创建和删除表单题目,是目前最通用且轻量的解决方式。

一、基础HTML结构
我们先准备一个容器用来存放题目,以及两个按钮分别控制添加和提交。题目本身不需要写在HTML里,而是由脚本生成后插入容器。
<div id="formContainer"></div> <button id="addBtn" type="button">添加题目</button> <button id="submitBtn" type="button">提交数据</button>
上面的代码中,formContainer作为动态内容的挂载点。两个按钮通过类型声明避免被浏览器当作表单提交按钮,这样我们可以完全用脚本控制行为。这种结构保持了页面干净,也方便后续用CSS统一控制题目块的样式。
二、题目模板与添加逻辑
动态添加的核心是用一个函数返回题目块的HTML字符串,然后把它转成节点插入页面。为了避免直接用innerHTML覆盖已有内容,我们使用appendChild配合模板字符串,这样已填写的内容不会被清空。
let questionIndex = 0;
function createQuestion() {
questionIndex++;
const wrapper = document.createElement('div');
wrapper.className = 'question-item';
wrapper.innerHTML = `
<p>题目 ${questionIndex}</p>
<input type="text" name="q${questionIndex}" placeholder="请输入答案" />
<button type="button" class="delBtn">删除</button>
`;
return wrapper;
}
document.getElementById('addBtn').addEventListener('click', function () {
const container = document.getElementById('formContainer');
container.appendChild(createQuestion());
});
在createQuestion函数中,我们用一个全局变量questionIndex记录题号,每次调用自增,保证name属性不重复。使用document.createElement创建外层容器,再赋值innerHTML,比直接拼接整个表单更安全,也方便后续绑定删除事件。
这种写法的好处是每次只追加新节点,老题目的输入值保留在DOM中,不会像整体重写innerHTML那样丢失。同时每个题目块独立成节点,删除时只需移除对应父元素即可。
三、删除题目与事件委托
如果给每个删除按钮单独绑定事件,题目增多后会产生大量监听器。更优的做法是在容器上用事件委托,通过判断目标元素的类名统一处理。
document.getElementById('formContainer').addEventListener('click', function (e) {
if (e.target && e.target.classList.contains('delBtn')) {
const item = e.target.closest('.question-item');
if (item) {
item.remove();
}
}
});
事件委托利用了冒泡机制,不论动态添加多少题目,只需要一个监听器。在上面的代码里,e.target指向被点击的元素,我们用classList.contains确认它是删除按钮,再通过closest找到题目块并移除。
这种方式显著降低了内存占用,也避免了题目重新编号时事件错乱的问题。即便后续把题目块结构改得更复杂,只要删除按钮的类名不变,逻辑就无需调整。
四、收集与提交数据
提交时不需要依赖题号连续,直接遍历容器内的所有输入项,将name和value收集成对象数组即可。
document.getElementById('submitBtn').addEventListener('click', function () {
const inputs = document.querySelectorAll('#formContainer input[type="text"]');
const result = [];
inputs.forEach(function (input) {
result.push({
name: input.name,
value: input.value
});
});
console.log(result);
});
这里使用querySelectorAll选中所有文本输入框,无论题目被删除还是新增,都能准确拿到当前页面上的有效数据。将结果打印到控制台只是示例,实际项目中可改为通过fetch发送给后端接口。
整体方案不依赖任何框架,兼容性好,逻辑清晰。后续若需要支持选择题、打分题等类型,只需在createQuestion中根据传入类型返回不同模板,其余添加、删除、收集逻辑都可复用。
JavaScript动态表单DOM操作修改时间:2026-08-06 09:54:23