加载外部HTML后操作DOM出现Uncaught TypeError: togBtn is null错误求助
问题原因与解决办法
核心问题
- 异步加载未被正确等待:
includeHTML内部用异步XMLHttpRequest加载HTML,但函数会立刻返回true——你的Promise刚创建就触发了resolve,此时外部HTML还没插入DOM,自然找不到menuBtn,调用addEventListener直接报错进入catch。 - 事件名语法错误:
addEventListener(click, toggleHamBtn)里的click没加引号,属于未定义变量,这也是触发报错的直接原因。
解决步骤
1. 重构includeHTML为Promise兼容版本
修改include-html-code.js,让它能正确反馈异步加载的完成状态:
function includeHTML() { return new Promise((resolve, reject) => { var z, i, elmnt, file, xhttp; z = document.getElementsByTagName("*"); let loadedCount = 0; let totalToLoad = 0; // 先统计需要加载的元素数量 for (i = 0; i < z.length; i++) { if (z[i].getAttribute("INCLUDE-HTML")) { totalToLoad++; } } if (totalToLoad === 0) { resolve(); return; } for (i = 0; i < z.length; i++) { elmnt = z[i]; file = elmnt.getAttribute("INCLUDE-HTML"); if (file) { xhttp = new XMLHttpRequest(); xhttp.onreadystatechange = function () { if (this.readyState == 4) { if (this.status == 200) { elmnt.innerHTML = this.responseText; } if (this.status == 404) { elmnt.innerHTML = "Page not found."; reject(new Error(`Failed to load ${file}`)); } elmnt.removeAttribute("INCLUDE-HTML"); loadedCount++; // 所有元素加载完成后resolve if (loadedCount === totalToLoad) { resolve(); } } }; xhttp.open("GET", file, true); xhttp.send(); } } }); }
2. 正确调用并绑定事件
修改index.html中的代码,等待includeHTML完成后再操作DOM,同时修正事件名的语法错误:
<head> <script src="../Scripts/include-html-code.js" type="text/javascript"></script> </head> <body> <div INCLUDE-HTML="../html-block/artillery-nav.html"></div> <script type="text/javascript"> // 用async/await等待加载完成 async function initNav() { try { await includeHTML(); console.log('导航栏加载完成'); const togBtn = document.getElementById('menuBtn'); // 注意click要加引号 togBtn.addEventListener('click', toggleHamBtn); function toggleHamBtn() { togBtn.classList.toggle('open'); } } catch (err) { console.error('加载导航栏失败:', err); } } initNav(); </script> </body> </html>
为什么之前的Promise写法无效?
你之前的Promise只是判断includeHTML()的返回值,但includeHTML不管异步请求完成没都会立刻返回true,等于完全没等待异步操作,自然拿不到刚加载的DOM元素。重构后的版本用Promise包裹整个异步加载流程,只有当所有HTML都插入DOM后才会resolve,此时再去获取元素就没问题了。
内容的提问来源于stack exchange,提问作者Artillery
相关产品推荐
相关产品推荐

