为什么document.querySelector('.list')返回null,实际存在对应class的ul标签
问题原因
- 核心是异步DOM注入的时序差:你使用的
data-include-html功能基于jQuery的AJAX请求实现,AJAX是异步操作,请求发送后不会等待响应返回,会直接继续执行后续脚本。你在ToDoApp/script.js中直接执行document.querySelector('.list')时,ToDoApp/index.html的内容还没有被AJAX响应注入到主页面DOM中,自然无法匹配到对应元素,返回null。 - 附加影响:
data-include-html.min.js中的逻辑包裹在$(function(){})中,本身就会等待DOMContentLoaded事件触发后才执行,进一步延后了HTML注入的时机,比直接在页面底部加载的ToDoApp/script.js执行时间更晚。 - 额外小问题:主页面和
ToDoApp/index.html中都存在id为todo-app的元素,id重复可能引发后续选择器异常,建议修改其中一个避免冲突。
解决方案
- 逻辑后置到DOM注入完成后执行
在ToDoApp/script.js中使用MutationObserver监听注入容器的内容变化,确认.list元素存在后再执行初始化逻辑:
function initTodoApp() { let list = document.querySelector('.list') console.log(list) const CHECK = {status:'completed', icon:'bx bxs-check-circle'}; const UNCHECK = {status:'not-completed', icon:'bx bx-circle'} let id = 0; let itemsList = [] // 其余业务逻辑都放在该函数内 } // 监听容器内容变化 const observer = new MutationObserver((mutations) => { if (document.querySelector('.list')) { initTodoApp() observer.disconnect() } }) observer.observe(document.getElementById('todo-app'), { childList: true, subtree: true })
脚本跟随HTML片段放置
把ToDoApp/script.js的<script>标签从主页面移除,添加到ToDoApp/index.html的末尾,这样当HTML片段被注入到主页面时,脚本才会执行,此时对应DOM已经存在,可以正常获取元素。临时调试方案
可以把DOM查询逻辑用setTimeout包裹延迟执行,仅适合调试使用,不推荐生产环境部署:
setTimeout(() => { let list = document.querySelector('.list') console.log(list) }, 100)
内容的提问来源于stack exchange,提问作者night_programmer
相关产品推荐
相关产品推荐

