document.getElementById返回null:已创建DOM元素无法获取的修复请求
问题:document.getElementById返回null,即使目标DOM元素已创建
问题详情
在开发TodoList网页时,创建了DOM元素todoWrapper并设置了id,但调用document.getElementById(todo.id)返回null,尽管todoWrapper本身不为null。控制台输出如下:
1
'...'
null
相关代码
index.js
let todolist = [{id:1 , label: "일어나기", completed: false}]; const renderTodo = async (todo) => { const todoWrapper = document.createElement('div'); todoWrapper.classList.add("todo-wrapper"); todoWrapper.id = todo.id; console.log(todoWrapper.id); console.log(todoWrapper); console.log(document.getElementById(todo.id)); const todoLabel = document.createElement('p'); todoLabel.className="todo-label"; todoWrapper.appendChild(todoLabel) todoLabel.innerText=todo.label; const todoActionWrapper = document.createElement('div'); todoActionWrapper.className="todo-action-wrapper"; todoWrapper.appendChild(todoActionWrapper); const completeButton = document.createElement('button'); completeButton.classList.add('todo-action'); completeButton.classList.add('complete'); if (!todo.completed){ completeButton.innerText="완료"; } else { completeButton.innerText="미완료"; } todoActionWrapper.appendChild(completeButton); const deleteButton = document.createElement('button'); deleteButton.classList.add('todo-action'); deleteButton.classList.add('delete'); todoActionWrapper.appendChild(deleteButton); deleteButton.innerText='삭제'; const addButton = document.getElementById('add-action'); const content = document.getElementById('content'); content.appendChild(todoWrapper); } const renderTodoList = () => { const content = document.getElementById('content'); content.innerHTML =""; todolist.forEach((todo) => { renderTodo(todo); }) } renderTodoList();
index.html
<!DOCTYPE html> <html> <head></head> <title>TO-DO web</title> <link href="./index.css" rel="stylesheet"/> <!-- <script src = "./index.js" defer></script> --> <body> <h1 id="title">오늘 할 일</h1> <div id="content"> </div> <div id="action-wrapper"> <button id="add-action">+</button> </div> <script src = "./index.js" defer></script> </body> </html>
原因分析
document.getElementById()只能查询已经挂载到文档DOM树中的元素。当前代码中,console.log(document.getElementById(todo.id))是在content.appendChild(todoWrapper)之前执行的,此时todoWrapper仅存在于内存中,还没有被添加到页面的DOM结构里,所以全局查询无法找到它,返回null。
解决方案
有两种可行的修改方式:
方式1:将查询代码移到元素挂载之后
把console.log(document.getElementById(todo.id))放到content.appendChild(todoWrapper)后面,确保元素已经加入DOM树:
const content = document.getElementById('content'); content.appendChild(todoWrapper); // 此时元素已挂载到DOM树,可正常查询 console.log(document.getElementById(todo.id));
方式2:直接使用已创建的变量(推荐)
如果只是需要引用这个元素,不需要通过getElementById查询,直接使用已经创建的todoWrapper变量即可,无需额外查询:
// 直接使用todoWrapper,不需要调用getElementById console.log(todoWrapper);
修改后的renderTodo函数示例
const renderTodo = async (todo) => { const todoWrapper = document.createElement('div'); todoWrapper.classList.add("todo-wrapper"); todoWrapper.id = todo.id; console.log(todoWrapper.id); console.log(todoWrapper); const todoLabel = document.createElement('p'); todoLabel.className="todo-label"; todoWrapper.appendChild(todoLabel) todoLabel.innerText=todo.label; const todoActionWrapper = document.createElement('div'); todoActionWrapper.className="todo-action-wrapper"; todoWrapper.appendChild(todoActionWrapper); const completeButton = document.createElement('button'); completeButton.classList.add('todo-action'); completeButton.classList.add('complete'); if (!todo.completed){ completeButton.innerText="완료"; } else { completeButton.innerText="미완료"; } todoActionWrapper.appendChild(completeButton); const deleteButton = document.createElement('button'); deleteButton.classList.add('todo-action'); deleteButton.classList.add('delete'); todoActionWrapper.appendChild(deleteButton); deleteButton.innerText='삭제'; const addButton = document.getElementById('add-action'); const content = document.getElementById('content'); content.appendChild(todoWrapper); // 移到挂载之后再查询 console.log(document.getElementById(todo.id)); }
内容的提问来源于stack exchange,提问作者offtheglass
相关产品推荐
相关产品推荐

