一位读者最近写信问我什么是 DOM。他们说他们已经听说过它,并隐约地了解过它,但并不确定自己是否真的理解了它。
我们可以解决这个问题。

但您编写的 HTML 会被浏览器解析并转换为 DOM。

查看源代码只会显示构成该页面的 HTML。这很可能是您编写的 HTML 的完全副本。
如果例如您在后端语言中的模板文件中工作并且不经常查看已编译的 HTML 输出,它可能看起来像不同的代码。或者,在您编写 HTML 后会发生一个“构建过程”,并且代码被输出到实时网站。也许该 HTML 被压缩或以其他方式更改。
查看源代码实际上有点奇怪。唯一关心查看该代码的人是开发人员,所有主要浏览器现在都内置了开发者工具。它可能已经失去了它的用处。

当您查看正在使用的任何 DevTools 中的面板时,该面板会显示看起来像 HTML 的内容,那就是 DOM 的可视化表示!我们做到了!

嗯,是的,它确实如此。请记住,它是直接从您的 HTML 创建的。在大多数简单情况下,DOM 的可视化表示将与您的简单 HTML 相同。
但它通常并不相同……
DOM 何时与 HTML 不同?
这是一种可能性:您的 HTML 中存在错误,浏览器已为您修复了它们。假设您的 HTML 中有一个 <table>
元素,但缺少必需的 <tbody>
元素。浏览器会为您插入该 <tbody>
。它将存在于 DOM 中,因此您可以使用 JavaScript 找到它并使用 CSS 对其进行样式设置,即使它不在您的 HTML 中。
但最有可能的情况是……
JavaScript 可以操作 DOM
假设您的 HTML 中有一个空元素,如下所示
<div id="container"></div>
然后在您的 HTML 中,有一段 JavaScript 代码
<script>
var container = document.getElementById("container");
container.innerHTML = "New Content!";
</script>
即使您不了解 JavaScript,您也可以推断出这段代码。在屏幕上,您将看到新内容!而不是什么都没有,因为那个空的 div
被填充了一些,嗯,新内容。
如果您使用 DevTools 查看 DOM 的可视化表示,您将看到
<div id="container">New Content!</div>
这与您的原始 HTML 或您在查看源代码中看到的内容不同。
Ajax 和模板
让我们不要深究,但我敢肯定,如果您要使用 Ajax 从其他地方获取内容并将其放到页面上,DOM 将与您的原始 HTML 大不相同。使用某种数据加载并使用 客户端模板 也是如此。
尝试访问 Gmail 并查看源代码。它只是一堆脚本和来自原始页面加载的数据。与您在屏幕上看到的内容相比,几乎无法识别。
JavaScript 与 DOM
JavaScript 是一种浏览器读取并执行操作的语言。但 DOM 是这些操作发生的地方。事实上,您可能认为的很多“JavaScript 东西”更准确地说是“DOM API”。
例如,我们可以编写 JavaScript 来监视元素上的 mouseenter
事件。但那个“元素”实际上是一个 DOM 节点。我们通过该 DOM 节点上的 DOM 属性附加该侦听器。当该事件发生时,是 DOM 节点发出该事件。

如果我说错任何内容,请见谅。但我希望您能理解我的意思。DOM 是这里的生命线。它是浏览器中所有事情发生的地方。JavaScript 只是语法,语言。它可以在完全没有 DOM API 的情况下在浏览器外部使用(请参阅 Node.js)。
这篇文章对我不够深入和详细。
好吧,DOM 代表“文档对象模型”,等等。我不想(也不具备资格)写那篇文章。以下是一些内容丰富的文章
- W3C:什么是文档对象模型?
- MDN:简介 - 文档对象模型
- 维基百科:文档对象模型
有用的教程!与“如果没有 doctype,它就不是网页”并列(不要害羞,我们都会偶尔出现这种尴尬的表情符号)。
不同意。它对我来说仍然至关重要。
澄清一下
我认为查看源代码的能力至关重要,应该很容易做到。我只是认为执行该命令应该在 DevTools 的“源”面板中打开文档,而不是在它自己的奇怪的小世界中孤立地进行这种特殊且独特的查看。
查看源代码仍然非常有用,适用于您实际上想要查看最初传递的标记的情况。也许您正在修复其他人的网站,或者您有一个动态生成的页面,您需要了解实际的输出内容。
能够查看生成的 DOM 无疑非常有用,但了解它的构建方式可以极大地帮助解决问题。
实际上,根据文章中::Chris:: 在上面的陈述,查看源代码在引入检查工具后,部分用途已不再适用..!
但是,当我们想要在单独的窗口中简单地打开源代码时,它仍然很重要,而不是打开网页控制台并打开相关选项卡以查看源代码。
尽管它不会消耗您的精力,但它只是提高了挫折时间,在高压高峰期(开个玩笑!)。
在调试可能以前没有接触过的代码时,查看源代码仍然非常有用。此外,查看源代码与 DOM 完全不同。有时您希望看到浏览器在 DOM 更改之前的状态。开发者工具处理了几乎所有来自查看源代码的角度的方面,但有时仍然可以快速查看源代码并了解发生了什么。
我认为 Chris 并沒有說它完全不相關。在大多数情况下,我们作为前端开发人员查看源代码时,我们会尝试查看哪些内容可能是 DOM 中存在对象的根源。为了帮助提高特异性和清晰度,检查元素会提供这一点。查看源代码可能有用,但实际上,如果我需要获取 HTML 文档的源代码,我会将网站镜像并在文本编辑器中打开它,因为这样阅读起来更清楚。
简单,但至关重要。
好文章!我想我之前没有意识到 DOM 与源代码之间的区别。可以理解它很容易被误解。
克里斯,这篇文章真的很有趣。我必须说,虽然我知道你写的 HTML 和 DOM 是不同的东西,但从视觉上我将它们视为一体。现在这篇文章帮助我进一步区分了它们。谢谢你的分享。
下一篇文章……影子 DOM?
这是一篇关于所有这些的优秀文章:https://css-tricks.org.cn/modular-future-web-components/
用最简单的术语来说,我认为可以这样说,DOM 是解析后的 HTML。
我可以试试吗?
HTML 代码到达
浏览器解释 HTML 并为页面构建 DOM
浏览器允许 JavaScript 改变 DOM
浏览器显示 DOM 的当前状态,始终是 DOM。
HTML 文档只是一个配方,一组关于浏览器如何为给定页面构建 DOM 的指令。我们最终看到的是浏览器如何解释这些指令。
DOM — 位于 HTML 代码和显示页面之间的一层 — 可能被引入(我是一个初学者,这是一个假设)以便在客户端呈现内容之前,允许在其中整理一些内容。现在它就在那里,显然通往屏幕的唯一途径就是通过它。
强烈反对。开发工具向你展示的也是 DOM 的当前状态,即你 HTML 的解释版本。
“查看源代码”是一个救生员,它允许你查看你的实际 HTML 代码。如果你正在制作动态组装的网页,“查看源代码”是检查你的代码最初要求浏览器做什么的最方便的地方。(检查是否有乱七八糟的/未关闭的 HTML 标签等等。(通过自定义 PHP 脚本组装 HTML 片段可能无法在第一次尝试时完美运行)。)
当然,W3C 验证器可以在这里提供最终的服务(前提是你可以将你的页面公开在线,但并非总是如此)。
此外,你也可以在开发工具中挖掘出原始的 HTML,但它似乎需要点击很多次,而且它的展示方式也比简单的全屏查看源代码更加笨拙。
不错的文章。有趣的是,每个人都知道 DOM — 但是当你想到它的时候,大多数初学者和一些高级 Web 开发人员可能会将其视为某种黑盒子。
我认为 DOM 和代码之间的关键区别在于,DOM 只能在运行时,在浏览器内部存在。对于 99% 的用例来说,它并没有什么区别,但我坚信,在教授任何形式的前端创作时,必须教授或至少回顾几个关键概念。
作为 HTML 作者,你正在编写一些将通过浏览器供人查看的内容
因此,你是在为浏览器编写代码
浏览器在读取你的代码时会构建对它的理解,这种理解被称为 DOM,它存在于浏览器内部。
标签(以 `<` 开头,以 `>` 结尾的文本片段)代表了关于如何构建 DOM 以及 DOM 的不同部分是什么的指令。
让它成为编写 HTML 的第一课,所有未来的开发都会变得有意义,没有它,你将会有很多学生试图弄清楚标签到底是什么,为什么它们很重要,以及标记语言中其他可能令人困惑的元素。对文本、标签和 DOM 之间关系的牢固理解,那么从 CSS 和 JavaScript 开始,所有其他内容都会顺畅地进行。
重要文章
如果你省略了可选标签(例如 ``、`
` 和 ``),则 DOM 可能与原始 HTML 不同。如果你的 HTML 如下所示
那么现代浏览器将在将 DOM 组合在一起之前,使用这些可选标签将其填充起来。
![result.png][http://i.imgur.com/kjvPdki.png]
没错。我尝试过编写一个没有结束标签的 HTML 文档。在“查看源代码”
模式下,它不会向我显示丢失的标签。但是,当我尝试使用 FireBug 检查页面时,它会向我显示丢失的标签。它自动添加了它!
感谢你发表这篇关于这个的文章!
我在过去 12 年里一直在使用 HTML,当有人提到 DOM 时我会感到很笨,因为我从未真正了解过它的正式含义。
超级简单的解释。谢谢克里斯!
DOM 是一个用于访问 HTML 和 XML 文档的编程面向对象的 API 定义。此 API 在 DOM 规范中使用称为 IDL 的语言中立语义进行定义。因此,从最严格的意义上说,以下说法是正确的:DOM 不会改变,除非 W3C 更改了 API 规范当你查看 `document.getElementById("firstheading")` 时,以下说法是正确的
因此,正如之前已经提到的,DOM 是一个 API 规范。因此,当你查看上面所示的开发工具时,你会看到由浏览器、模板或脚本更改的 HTML 或 XML 标记(即文档),以及你看到的 JavaScript。JavaScript 可能会被看到访问 DOM API,但标记只是一个文档,JavaScript 是一种语言,它可能会访问符合 DOM 规范的 API。如果你想“查看 DOM”,请点击上面博文末尾提供的链接,阅读 W3C DOM 规范。开发工具实际上是展示了一种语言,JavaScript,它使用 DOM API 来传递与 HTML 或 XML 文档相对应的 数据和对象。
谢谢克里斯,很棒且有用的文章
很棒的文章,有很棒的解释图形。特别是初学者可以从中学到一些东西。如果没有其他,克里斯是一位文章大师和老师。这就是我们所有人订阅的原因。我们知道我们可以从这个家伙那里学到一些东西。
感谢你发表这篇简短的文章,我今天一直在尝试向自己解释,这有助于澄清它:D
感谢你发表这篇博文,克里斯!它一直是那些对我来说很模糊的首字母缩略词之一。关于查看源代码,我在接触潜在客户时经常使用它。它让我快速了解他们的网站是如何工作的(如果有的话),以及我可以提供什么来推动他们可能拥有的目标。
这很奇怪,最近几天,关于 DOM 的信息似乎在各个地方都冒出来。
然后今天早上我在 failblog 上看到了这个 http://cheezburger.com/7974345216,觉得它很有趣。我认为她被“DOMED”了:P
干得好,克里斯!我唯一可能做出的调整是关于 DOM 修正 HTML“错误”的说法。虽然这种情况肯定可能发生,但说 DOM“润色” HTML 可能更准确;例如,在 HTML5 中,不需要关闭列表项标签,将它们从代码中省略是完全有效的,但 DOM 在解析页面时会插入它们。属性值的引号也是如此。只要开发人员有意识地这样做,这些就不是“错误”,本身。 (我知道你不建议这样做,但我认为这是一种风格差异,而不是“对错”的战场)。
过去我将 HTML 和 DOM 对比为认知:HTML 是页面的存储的“长期记忆”,而 DOM 是“短期记忆”:短暂的、转瞬即逝的更改和印象。
我有一个简短的版本:DOM 是浏览器在向你展示网页时“心中所想”的总和。
源代码、脚本、CSS、图像、API 等等,所有这些都有助于它。
很棒的解释。谢谢克里斯。
我不确定如何向没有计算机科学学位的人解释这一点,但我尽力而为:DOM 是抽象地被称为“数据结构”的东西,更具体地说,是一种“[树数据结构](https://en.wikipedia.org/wiki/Tree_(data_structure))”。
如果你想更好地了解如何更新 DOM,你可能想看一些关于如何一般性地使用树数据结构的示例。从学习递归开始,然后编写自己的链接列表,然后转向树。作为一个挑战,尝试修改你构建的树,例如创建、删除和更新节点。也许,为了真正挑战自己,将树转换为扁平列表。这需要称为“遍历”的操作。
我希望我在尝试找到对 DOM 的简洁/实际解释时能够看到这一点,太棒了!
我后来发现这个也相当有用:http://domenlightenment.com/
干杯
Ed
优秀的帖子和链接..!
谢谢 Ed
已接受。 ;-) 实际上,你确实这样做了,我想
在 HTML 4 中,tbody 元素是必需的,但开始和结束标签不是。这意味着无论您在代码中是否包含 tbody 的开始和结束标签,tbody 元素始终存在于表格中。
您不能省略 tbody 元素。您可以省略标签,因为两者都是可选的(DTD 行
<!ELEMENT TBODY O O (TR)+ -- table body -->
中的 Os)。这意味着 tr 元素永远不会是 table 元素的子元素,而是它们的孙子元素,即使在代码中
<table>
和<tr>
之间没有其他标签。XHTML 1 中的情况不同,因为没有可选标签。为了与 HTML 4 兼容,必须允许编码人员选择包含 tbody 标签或省略它们。因此,tr 元素允许作为 table 元素的子元素,而 tbody 元素不是必需的。
没有 tbody 标签的 XHTML 1 文档,以 XML 处理(
application/xhtml+xml
或类似媒体类型)将生成一个 DOM,其中 tr 元素是 table 元素的子元素。而以 HTML 处理(
text/html
)时,将应用 HTML 4 规则。这意味着从同一 XHTML 1 源代码生成的 DOM 不同,具体取决于媒体类型。这比预期的更成问题。最佳实践是在 XHTML 1 中始终使用 tbody 标签。在 HTML5 中,table 元素的内容模型包括“零个或多个 tbody 元素或一个或多个 tr 元素”,即 tbody 元素在 HTML5 语法中不是必需的。
但即使没有 tbody 标签,HTML5 解析器也会在 DOM 中生成一个 tbody 节点,模仿 HTML 4 中相同的行为。
重要的澄清。如果您使用 CSS 直接子规则进行样式设置,这种区别可能很重要;根据解释材料的解析器,规则可能无法应用。最好保持一致,并在讨论表格时始终使用通用后代规则...
Chris 的好文章,很高兴看到并阅读一些不同的回应。我偶尔会访问您的网站,发现了很多灵感,对我来说是一个非常棒的资源。
继续努力。
我们可以得到那个猫头鹰演示的链接吗?
http://codepen.io/m3uc/pen/EyJGv
这个问题的答案在几周前我才真正理解,当时我试图弄清楚“为什么 Modernizr 不起作用”。在那个时候,它确实起作用了——但它添加的类没有出现在“查看源代码”中——只出现在浏览器的检查器中。然后我意识到。这就是所有区别所在。
真有趣,我已经做了这么长时间的网页开发了,但我仍然没有理解这些小细节。我想这并不罕见,很多网站给了你各种各样的解释。感谢您的直观演示。
在编写 JavaScript 时,我们主要直接处理 DOM,它在浏览器的源代码或开发工具中更容易看到。感谢 Chris 的详细解释
我同意 Jessica 以上的观点,我从未想过 DOM 的这些小细节,多年来一直在玩弄 DOM。这让我想要向下一个我面试的开发者提出一个关于 DOM 的问题 :-)
太棒了!