简单地说,我尝试了 async 和 defer 方法,以及移动 script 标签,试图让 dom 操作起作用。我认为这可能只是代码的问题,因为两者都没有解决问题。我直接从 Odin 项目的示例中复制粘贴的代码,所以我不太确定出了什么问题。以下是 HTML 和 JS 文件。
const container = document.querySelector('#container');
const content = document.createElement('div');
content.classList.add('content');
content.textContent = 'This is the glorious text-content!';
container.appendChild(content);
const para = document.createElement('p');
para.classList.add('para');
para.textContent = 'This is the fun times!';
container.appendChild(para);
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>DOM Manipulation</title>
<script defer src="index.js"></script>
</head>
<body>
<h1>
THE TITLE OF YOUR WEBPAGE
</h1>
<div className="container"></div>
</body>
</html>
具体来说,第一个appendChild之后的整个部分基本上没什么用,可以暂时删除。具体错误是“Uncaught TypeError: Cannot read properties of null (reading 'appendChild')” at index.js:8:11.
我也尝试过改变编写代码的方式,但我无法理解为什么这是一个问题,即使将脚本链接移至底部并同时使用 async + defer 也是如此。我已经尝试了 3 个解决方案的所有组合,但我无法让它发挥作用。
我不太明白为什么 DOM 似乎强迫自己比 HTML 加载得更快,尽管我尝试了一切方法来减慢它的速度。我还清除了缓存,甚至多次,只是为了确保这不是缓存问题。我正在使用实时服务器扩展运行此测试,确保保存,我什至尝试将其作为本地文件加载。
起初,我实际上通过将 createElement("div") 错误地输入为 querySelector("div") 来使顶部部分正常工作,但后来我尝试创建下一个元素(P),就在那时我注意到当试图查看为什么我的 P 不工作时,控制台出现错误(笑)。
我知道还有一些其他潜在的修复,window.onload(我不知道真正的拼写)和窗口加载时的 addEventListener,但为什么 HTML 的 defer/async/bottom 不起作用?这没有任何意义,我不想在不理解问题的情况下继续前进。
根据您提供的代码,问题似乎在于您如何在 JavaScript 中选择容器。
在您的 HTML 中: 在你的 JS 中:
const container = document.querySelector('#container');
您正在尝试选择具有 ID 容器的元素,但您已在 HTML 中为您的 div 指定了容器类。类的正确选择器是 。 (点),ID 为 #(散列)。
要修复该错误,您可以执行以下操作之一:
将类更改为 HTML 中的 ID:
<div id="container"></div>
更改 JavaScript 以选择使用类:
const container = document.querySelector('.container');
如果您采用第一个解决方案,您当前的 JS 代码将无需更改即可工作。如果您采用第二种解决方案,则只需更改 JS 中的这一行即可。
一旦进行此更改,错误应该得到解决,并且 DOM 操作将按预期工作,即使在脚本标记上有延迟也是如此。
关于您关于延迟、异步和脚本放置的问题:
defer:该属性告诉浏览器在解析 HTML 后执行脚本。它保证脚本将按照它们在文档中出现的顺序执行。
async:此属性告诉浏览器在脚本可用时立即执行该脚本,这可能是在解析 HTML 之前或之后。异步加载的脚本的执行顺序无法保证。
将脚本放在 的底部:这可以确保在脚本运行之前已经解析了脚本上方的 HTML。
在您的情况下,使用 defer 应该就足够了,因为它确保脚本在 HTML 解析后运行。问题在于 JS 代码中的选择器错误。
尝试一下并告诉我。
const container = document.querySelector('.container');
const content = document.createElement('div');
content.classList.add('content');
content.textContent = 'This is the glorious text-content!';
container.appendChild(content);
const para = document.createElement('p');
para.classList.add('para');
para.textContent = 'This is the fun times!';
container.appendChild(para);
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>DOM Manipulation</title>
<script defer src="index.js"></script>
</head>
<body>
<h1>
THE TITLE OF YOUR WEBPAGE
</h1>
<div class="container"></div>
</body>
</html>