JavaScript中Checkbox设置checked属性后页面未渲染选中状态问题
页面上有一个带复选框的表单,选项通过服务器端分页加载,点击上下页时会加载新选项并移除旧选项。我用一个Set变量保存已选中的值:
let selectedReaders = new Set();
想要实现的效果是:加载新选项时,判断该值是否已被选中,若是则将对应复选框设为选中状态。
我在添加每个选项的HTML代码时,会判断并设置复选框的checked属性,但页面上所有复选框始终显示未选中状态。代码如下:
for(let reader of serverReaders){ readers.innerHTML += ` <div class="form-check form-check-inline"> <input class="form-check-input me-1" type="checkbox" onclick="addReader(this)" value="${reader.userID}" id="reader-${reader.userID}" > <label class="form-check-label" for="reader-${reader.userID}">${reader.username}</label> </div>` document.getElementById(`reader-${reader.userID}`).checked = [...selectedReaders].some( id => id === reader.userID) console.log(document.getElementById(`reader-${reader.userID}`).checked) }
逻辑是先添加复选框和标签,再判断selectedReaders里是否存在当前reader的ID,存在就把checked设为true,否则设为false。console.log能正确输出true,但页面上的复选框就是不显示选中状态,请问哪里出错了?
问题出在使用innerHTML +=拼接HTML的方式:每次拼接后,浏览器会重新解析整个readers元素的内容,导致你刚刚设置的checked状态被重置。简单来说,你刚给复选框设了checked=true,浏览器就重新渲染了整个容器内的元素,新渲染的元素是基于你拼接的原始HTML字符串(没有checked属性),之前的设置自然就被覆盖了。
修复方法有两种:
提前在HTML字符串中加入checked属性
直接在拼接HTML时,判断当前reader的ID是否在selectedReaders里,动态添加checked属性:for(let reader of serverReaders){ const isChecked = selectedReaders.has(reader.userID); readers.innerHTML += ` <div class="form-check form-check-inline"> <input class="form-check-input me-1" type="checkbox" onclick="addReader(this)" value="${reader.userID}" id="reader-${reader.userID}" ${isChecked ? 'checked' : ''} > <label class="form-check-label" for="reader-${reader.userID}">${reader.username}</label> </div>` }这里用
selectedReaders.has()代替some,效率更高——Set的has方法是O(1)时间复杂度,而展开成数组用some是O(n)。创建DOM元素而非拼接字符串
用原生DOM API逐个创建元素,设置好属性后再添加到readers容器中,彻底避免渲染重置的问题:for(let reader of serverReaders){ const isChecked = selectedReaders.has(reader.userID); // 创建外层div const div = document.createElement('div'); div.className = 'form-check form-check-inline'; // 创建复选框 const input = document.createElement('input'); input.className = 'form-check-input me-1'; input.type = 'checkbox'; input.onclick = () => addReader(input); input.value = reader.userID; input.id = `reader-${reader.userID}`; input.checked = isChecked; // 创建标签 const label = document.createElement('label'); label.className = 'form-check-label'; label.htmlFor = `reader-${reader.userID}`; label.textContent = reader.username; // 组装并添加到容器 div.appendChild(input); div.appendChild(label); readers.appendChild(div); }这种方式更可靠,也更易于维护,能避免HTML字符串拼接带来的各种潜在问题。
内容的提问来源于Stack Exchange,提问作者Barracuda

