JavaScript 创建带默认选中值的动态下拉列表 仅末位默认值生效问题
问题根因
出现“仅最后一个下拉菜单生效默认值”的现象,核心是innerHTML +=的操作机制导致:
每执行一次table.innerHTML += 新行字符串,浏览器并不会在原有DOM基础上追加内容,而是执行以下流程:
- 把当前节点下所有已存在的DOM元素序列化成纯HTML字符串
- 拼接上当前新生成的行字符串
- 重新解析整个字符串,生成一套全新的DOM树替换原有全部内容
这就导致每循环生成一行新内容,之前已经追加到表格里的下拉选择框、动态塞入的选项、已经设置好的默认值,全都会被销毁重建。只有最后一次循环结束后,没有再触发innerHTML重写操作,最后一行的下拉框设置才会留存,前面所有的设置都会被后续的重写操作完全覆盖。
原代码还存在两个附带逻辑问题:
- 操作的DOM节点选错:代码取了整个
#myTable表格元素做innerHTML追加,实际应该操作内部的#pabBodytbody节点,不然每次重写HTML都会把原本的表头结构冲乱 - 行内标签不匹配:生成的行HTML里把
<td>的闭合标签错写成了</th>,容易引发浏览器解析异常
修正方案
两种可落地的修复思路,任意选择即可:
- 循环过程中不要反复写入innerHTML,先把所有要生成的行拼成完整字符串,循环结束后一次性写入tbody,避免多次触发DOM全局重建
- 全程使用DOM原生API创建行、单元格、下拉框元素,直接追加到tbody节点下,不使用innerHTML拼接,自然不会出现DOM被整体替换的问题
修正后的可运行代码示例:
let brand = [ {"brand": "audi"}, {"brand": "mercedes"} ] $(document).ready(function() { createTableBody() }) function createTableBody() { // 直接选取tbody节点,避免操作整个表格元素 var tableBody = document.getElementById('pabBody') let rowHtmlList = [] // 循环内仅拼接字符串,不做DOM写入操作 for (var i = 0; i < 5; i++) { rowHtmlList.push(`<tr> <td>${i}</td> <td><select class="brand" id="brand${i}"> <option value="">brand</option> </select></td> </tr>`) } // 所有行的HTML一次性写入DOM tableBody.innerHTML = rowHtmlList.join('') // 全量DOM插入完成后,再统一做选项填充、默认值设置 for (var i = 0; i < 5; i++) { createDropdown(brand, i) } } function createDropdown(data, x) { var selectList = document.getElementById('brand' + x) for (var i = 0; i < data.length; i++) { var option = document.createElement("option") option.value = data[i].brand option.text = data[i].brand selectList.appendChild(option) } // 此时设置的默认值不会被后续DOM重写操作覆盖 selectList.value = "mercedes" }
注意:只要循环过程中还存在innerHTML重写操作,每生成一个下拉框就马上设值的逻辑必然会被后续操作冲掉。等所有DOM结构完全插入页面后,再统一执行选项填充、默认值设置,就能从根本上解决这个问题。
内容的提问来源于stack exchange,提问作者Klaus M.
相关产品推荐
相关产品推荐

