JavaScript中获取innerHTML内标签修改样式失败问题求助
解决innerHTML生成DOM后无法获取元素修改样式的报错问题
问题场景
通过innerHTML循环生成包含.rule-body类的DOM结构,代码如下:
ruleData.forEach((rule) => { rulesWrapper.innerHTML += ` <div class='rule'> <div id='rule-title' class='rule-title' onclick='showRuleDetail(${counter})'> <div> <p>${counter}.</p> <p>${rule.title}</p> </div> <svg width="20" height="21" viewBox="0 0 20 21" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M12.5 5.5L7.5 10.5L12.5 15.5" stroke="#1E1E20" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> </svg> </div> <div class='rule-body'> <p>${rule.body}</p> </div> </div> `; counter++; });
随后尝试获取.rule-body元素并修改背景色:
let ruleBody = document.querySelectorAll('.rule-body'); ruleBody[0].style.background = 'red';
运行时报错:
TypeError: Cannot read properties of undefined (reading 'style')
解决方案
1. 确保DOM生成代码优先执行
报错核心原因是获取元素的代码在DOM生成完成前就执行了,此时querySelectorAll('.rule-body')返回空的NodeList,访问索引[0]自然会得到undefined。
调整代码顺序,把获取和修改样式的逻辑放在DOM生成循环之后,同时增加长度判断避免空值报错:
// 先执行DOM生成逻辑 ruleData.forEach((rule) => { rulesWrapper.innerHTML += ` <div class='rule'> <div id='rule-title' class='rule-title' onclick='showRuleDetail(${counter})'> <div> <p>${counter}.</p> <p>${rule.title}</p> </div> <svg width="20" height="21" viewBox="0 0 20 21" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M12.5 5.5L7.5 10.5L12.5 15.5" stroke="#1E1E20" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> </svg> </div> <div class='rule-body'> <p>${rule.body}</p> </div> </div> `; counter++; }); // 再执行获取和修改样式的逻辑 let ruleBody = document.querySelectorAll('.rule-body'); if (ruleBody.length > 0) { ruleBody[0].style.background = 'red'; }
2. 校验数据源是否为空
如果ruleData是空数组,循环不会生成任何.rule-body元素,同样会导致ruleBody为空。可以先做数据源校验:
if (ruleData.length === 0) { console.log('无可用规则数据'); return; } // 后续执行DOM生成和样式修改逻辑 ruleData.forEach(/* ... */);
3. 改用DOM创建API替代innerHTML(推荐)
使用document.createElement创建元素,既能避免innerHTML重复渲染的性能问题,还能直接获取生成的.rule-body元素,无需事后查询:
ruleData.forEach((rule) => { // 创建外层容器 const ruleDiv = document.createElement('div'); ruleDiv.className = 'rule'; // 构建rule-title模块 const ruleTitle = document.createElement('div'); ruleTitle.id = 'rule-title'; ruleTitle.className = 'rule-title'; ruleTitle.onclick = () => showRuleDetail(counter); const titleInner = document.createElement('div'); const numP = document.createElement('p'); numP.textContent = `${counter}.`; const titleP = document.createElement('p'); titleP.textContent = rule.title; titleInner.appendChild(numP); titleInner.appendChild(titleP); const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); svg.setAttribute('width', '20'); svg.setAttribute('height', '21'); svg.setAttribute('viewBox', '0 0 20 21'); svg.setAttribute('fill', 'none'); const path = document.createElementNS('http://www.w3.org/2000/svg', 'path'); path.setAttribute('d', 'M12.5 5.5L7.5 10.5L12.5 15.5'); path.setAttribute('stroke', '#1E1E20'); path.setAttribute('stroke-width', '1.5'); path.setAttribute('stroke-linecap', 'round'); path.setAttribute('stroke-linejoin', 'round'); svg.appendChild(path); ruleTitle.appendChild(titleInner); ruleTitle.appendChild(svg); // 构建rule-body模块 const ruleBody = document.createElement('div'); ruleBody.className = 'rule-body'; const bodyP = document.createElement('p'); bodyP.textContent = rule.body; ruleBody.appendChild(bodyP); // 组装所有元素并添加到页面 ruleDiv.appendChild(ruleTitle); ruleDiv.appendChild(ruleBody); rulesWrapper.appendChild(ruleDiv); // 直接修改当前生成的rule-body样式(按需) if (counter === 0) { ruleBody.style.background = 'red'; } counter++; });
内容的提问来源于stack exchange,提问作者Navid Azimi
相关产品推荐
相关产品推荐

