函数内动态创建JavaScript对象:多次调用后子对象为空的问题
解决appendDiv多次调用后新创建的子对象为空的问题
我一眼就看出问题出在重复绑定表单submit事件以及DOM选择器的作用范围上,咱们一步步拆解核心问题:
重复绑定submit事件:每次调用
appendDiv,你都会给$('#creates')新增一个submit事件处理函数。当表单最终提交时,所有绑定的处理函数都会依次执行——第一个处理函数里的current_id还是第一次调用时的旧ID,它会继续修改旧对象;而新的处理函数虽然拿着新ID,但因为逻辑冲突,根本没正确给新子对象赋值。全局DOM选择器的问题:你用
document.querySelectorAll('.period-select')获取的是页面上所有类名为period-select的元素,而不是和当前current_id对应的那一组。如果多次调用appendDiv新增了多组元素,拿到的值会混乱,导致新子对象无法正确赋值。变量作用域与初始化时机:你在
appendDiv调用时就直接把dataObject[${current_id}]设为空对象,但submit是异步触发的——如果用户调用第二次appendDiv后还没提交表单,新子对象自然是空的;但你说提交后还是空,核心还是前面两个问题导致赋值逻辑没执行。
修复后的代码示例
let dataObject = {}; // 只绑定一次submit事件,避免重复绑定导致的逻辑冲突 $('#creates').submit(function (event) { event.preventDefault(); // 必须阻止表单默认提交,否则页面刷新会丢失所有数据 // 动态获取当前要操作的ID(这里需要你根据实际场景调整,比如从触发元素的标识/自定义属性获取) const current_id = event.target.dataset.targetId; // 示例:假设用自定义属性存目标ID // 确保子对象存在,避免报错 if (!dataObject[current_id]) { dataObject[current_id] = {}; } const nbrGroupValue = parseInt(document.getElementById('nbr_group').value, 10); // 精准选择当前分组下的period-select元素,而非全局所有 const periodSelects = document.querySelectorAll(`#${current_id} .period-select`); const inputList = []; for (let j = 0; j < 3; j++) { inputList[j] = periodSelects[j].value; } // 赋值到对应子对象 for (let i = 0; i < nbrGroupValue; i++) { dataObject[current_id][i] = { firstvalue: inputList[0], secondvalue: inputList[1], thirdvalue: inputList[2] }; } console.log(dataObject); // 可打印验证结果 }); function appendDiv() { const e = event.target; const current_id = e.id; // 提前初始化子对象(可选,也可以在submit时再做) if (!dataObject[current_id]) { dataObject[current_id] = {}; } // 这里添加你新增DOM元素的逻辑,比如给表单添加对应分组的period-select // 注意要把current_id关联到新增的元素上,比如给表单加data-targetId="${current_id}" // ...你的DOM操作代码... }
关键改进点
- 单次绑定submit事件:把事件绑定移到
appendDiv外部,只执行一次,彻底避免多处理函数冲突的问题。 - 精准选择DOM元素:通过
#${current_id} .period-select限定选择范围,只获取当前分组下的元素,确保值的准确性。 - 阻止表单默认行为:加上
event.preventDefault(),避免页面刷新导致数据丢失,这是表单处理的常见坑。 - 避免全局变量污染:用
const/let声明变量,替代var和全局变量,减少意外的作用域问题。
如果你的场景是每次调用appendDiv会新增独立表单,更推荐用事件委托的方式(绑定到父元素,通过冒泡处理动态新增的表单),灵活性更高:
let dataObject = {}; // 事件委托:绑定到父容器,处理所有动态新增的表单 $('#form-container').on('submit', '.group-form', function (event) { event.preventDefault(); const form = this; const current_id = form.dataset.id; // 从表单自定义属性获取ID if (!dataObject[current_id]) dataObject[current_id] = {}; const nbrGroupValue = parseInt(form.querySelector('.nbr_group').value, 10); const periodSelects = form.querySelectorAll('.period-select'); const inputList = Array.from(periodSelects).map(el => el.value); for (let i = 0; i < nbrGroupValue; i++) { dataObject[current_id][i] = { firstvalue: inputList[0], secondvalue: inputList[1], thirdvalue: inputList[2] }; } }); function appendDiv() { const e = event.target; const current_id = e.id; // 创建新表单并关联ID const newForm = document.createElement('form'); newForm.className = 'group-form'; newForm.dataset.id = current_id; // 添加表单元素(nbr_group、period-select等) // ...你的DOM构建代码... document.getElementById('form-container').appendChild(newForm); }
内容的提问来源于stack exchange,提问作者Yacin Omar
相关产品推荐
相关产品推荐

