getElementsByClassName获取元素时报Cannot read property 'style' of undefined如何解决
问题原因
- JS执行时机早于DOM渲染完成:调用
showTab(currentTab)的代码如果放在<head>标签内,或者放在.tab类DOM元素的代码上方,执行代码时页面还未完成DOM渲染,document.getElementsByClassName('tab')此时返回的是空集合,访问x[n]自然返回undefined。控制台打印HTMLCollection时能看到元素是因为HTMLCollection为动态集合,打印时仅存储引用,等你手动在控制台展开查看时,页面已经完成DOM渲染,因此能看到完整元素,但代码实际执行的时间点确实无法获取到对应元素。 - 页码下标越界:如果是切换分页步骤时出现报错,是因为
nextPrev函数未做边界限制,导致currentTab的数值小于0,或者大于等于.tab元素的总数量,访问x[n]时下标超出集合范围。
解决方案
1 修正JS执行时机
两种方案二选一即可:
- 方案一:将所有JS代码移动到
</body>闭合标签的前面,保证所有DOM元素渲染完成后再执行JS逻辑。 - 方案二:给初始化代码包裹DOM加载完成监听事件:
document.addEventListener('DOMContentLoaded', function () { var currentTab = 0 showTab(currentTab) }) // 其余函数逻辑放在监听外即可
2 增加边界判断
在showTab函数中首先对入参和元素集合做合法性校验,避免下标越界报错:
function showTab(n) { var x = document.getElementsByClassName('tab') // 无tab元素直接退出 if (x.length === 0) return // 修正非法下标 n = Math.max(0, Math.min(n, x.length - 1)) currentTab = n // 同步修正全局当前页码 x[n].style.display = 'block' if (n == 0) { document.getElementById('prevBtn').style.display = 'none' } else { document.getElementById('prevBtn').style.display = 'inline' } if (n == x.length - 1) { document.getElementById('nextBtn').innerHTML = 'Submit' } else { document.getElementById('nextBtn').innerHTML = 'Next' } fixStepIndicator(n) }
同时补全nextPrev函数的边界校验逻辑:
function nextPrev(step) { var x = document.getElementsByClassName('tab') currentTab += step // 到达最后一页点击next则提交表单 if (currentTab >= x.length) { document.getElementById('agentForm').submit() return } showTab(currentTab) }
注意:需自行补全
fixStepIndicator函数的逻辑,该函数用于修改步骤指示器的激活样式,未定义会触发额外报错。
内容的提问来源于stack exchange,提问作者Mayukh Dasgupta
相关产品推荐
相关产品推荐

