JS单词匹配练习工具新增输入项后生成HTML重复创建元素问题
问题根因
- 核心原因:
generate_html函数的旧内容清理逻辑判断条件为addMore && htmlGenerated,但add_more方法执行时会主动将htmlGenerated设置为false,导致新增输入项后触发generate_html时,旧内容清理逻辑永远不会执行,旧的textarea和控制按钮未被删除,就会重复生成新的控件。 - 附带逻辑缺陷:你生成HTML内容的循环起始值为
numberOfInputs,会导致前2组初始输入的内容不会被加入生成的HTML中。
修复方案
直接修改generate_html函数,先做全局旧内容清理,再执行生成逻辑,同时修正循环索引问题:
function generate_html() { // 第一步:统一清理所有旧内容,不依赖状态变量判断,直接检测DOM是否存在 // 清理旧的textarea const oldTextarea = document.getElementById("generated_html_textarea"); if (oldTextarea) oldTextarea.remove(); // 清理旧的控制按钮栏 const oldControls = document.getElementById("program1"); if (oldControls) oldControls.remove(); // 清理已渲染的HTML内容,符合你原有设计要求 const oldRendered = document.getElementById("rendered_html"); if (oldRendered) oldRendered.remove(); // 重置相关状态变量 htmlGenerated = false; htmlRendered = false; // 原有生成逻辑,修正循环索引 const e_inputs = document.querySelectorAll("[id^='el']"); const d_inputs = document.querySelectorAll("[id^='dl']"); const title = document.getElementById('title_input').value; let elArray = []; let dlArray = []; e_inputs.forEach( i => { if(i.value) elArray.push(i.value) }); d_inputs.forEach( i => { if(i.value) dlArray.push(i.value) }); let text = title + "\n"; // 修正循环起始值为0,遍历所有输入内容 for (let i = 0; i < elArray.length; i++) { text += `${elArray[i]}:${dlArray[i]}\n`; } //fetch the results box results = document.getElementById("results"); //create textarea textarea = document.createElement("textarea"); textarea.setAttribute("id","generated_html_textarea"); // initialize blank html html = ''; //create key inputs,修正循环起始值为0 for (let i = 0; i < elArray.length; i++){ html += '<div id="s'; id = (i+1); html += id; html +='" class="draggyBox-small">'; html += elArray[i]; html +='</div>\n'; } //create description inputs,修正循环起始值为0 html += '<table id="tablestyle">' for (let i = 0; i < dlArray.length; i++){ html += '<td id="row'; id = (i+1); html += id; html +='">\n'; html += '\t\t<div id="t'; html +=i; html +='" class="ltarget"></div>\n \t</td >\n \t<td id="d2">' html +=dlArray[i]; html +='</td >\n </tr>\n'; } html += '</table>'; // html generation is done. htmlGenerated = true; textarea.value = html; results.appendChild(textarea); // Generate reset, show answer, and render html buttons controls = document.createElement("div"); controls.setAttribute("id","program1"); controls.setAttribute("style","border: 1px solid #EB0D1B; width: 360px; font-family: courier; font-size: 100.5%; margin: 0px auto; border: 1px; text-align: center; margin-top: 5px;"); controls.innerHTML += '<span style="padding: 3px"> <button id ="one" class="button" type="button" onClick="one()">Show Answer</button> <button id = "resetButton" class="button" type="button" onClick="reset()">Reset</button><button id = "renderHTMLButton" class="button" type="button" onClick="render_html()">Render html</button> <span id = "audio" style=""> <a href="" title="Turns Text-to-Speech Output On or Off" class="menulink" style="text-decoration: none;"><img id="bg" src="audioOff.png" height="30" width="30" style="margin-bottom:-10px; padding-bottom:-20px;"/> </a> </span> </span>'; results.appendChild(controls); }
可选优化(符合原有设计逻辑)
修改render_html函数,支持重复点击时更新渲染内容:
function render_html(){ // 先清理已渲染的旧内容 const oldRendered = document.getElementById("rendered_html"); if (oldRendered) oldRendered.remove(); textarea = document.getElementById("generated_html_textarea"); generated_html = textarea.value; maincontentstyle = document.getElementById("maincontentstyle"); rendered_html = document.createElement("div"); rendered_html.setAttribute("id","rendered_html"); rendered_html.setAttribute("style","border: 1px solid #EB0D1B; width: 360px; font-family: courier; font-size: 100.5%; margin: 0px auto; border: 1px; text-align: center; margin-top: 5px;"); rendered_html.innerHTML += generated_html; maincontentstyle.appendChild(rendered_html); htmlRendered = true; }
内容的提问来源于stack exchange,提问作者Evan Gertis
相关产品推荐
相关产品推荐

