我们都听说过与JavaScript相关的DOM或文档对象模型。DOM是Web开发中一个非常重要的概念。没有它,我们就无法在浏览器中动态修改HTML页面。
学习和理解DOM可以更好地访问、修改改和监听HTML页面的不同元素。文档对象模型还可以帮助我们减少不必要的脚本执行时间增加。

另请阅读:​​15个用于Web开发人员DOM操作的javascript方法​

数据结构树节点

在讨论dom是什么,它是如何产生的,它是如何存在的,以及它内部发生了什么之前,我想让您了解树。不是针叶树和落叶树,而是数据结构树。

如果我们简化数据结构的定义,就更容易理解它的概念。我想说,数据结构是关于安排数据的。是的,只是简单的旧安排,就像你把家里的家具或书放在书架上,或是把所有不同的食物组放在盘子里,以便让它对你有意义一样。

当然,这并不是数据结构的全部功能,但这几乎就是所有功能的起点。这种“安排”是一切的核心。它在DOM中也非常重要。但我们还没有讨论DOM,所以让我引导您使用一种您可能熟悉的数据结构:数组。

数组与树

数组具有索引和长度,它们可以是多维的,并且具有更多的特性。尽管了解数组的这些内容很重要,但我们现在不要为此而烦恼。当你把不同的事情排成一行的时候。对我们来说,数组非常简单。

详细了解文档对象模型(DOM)_html


同样,当我们想到树的时候,比如说,它是把东西放在另一个下面,从顶部的一个东西开始。

详细了解文档对象模型(DOM)_dom_02

现在,你可以从以前的单列鸭子身上取下来,把它竖起来,告诉我“现在,每只鸭子都在另一只鸭子下面”。那是棵树吗?它是。

根据您的数据是什么,或者您将如何使用它,树中最顶层的数据(称为根)可能是非常重要的数据,或者只是在树下包含其他元素的数据。

不管怎样,树数据结构中最顶层的元素都会起到非常重要的作用。它提供了一个开始搜索我们想要从树中提取的任何信息的位置。

详细了解文档对象模型(DOM)_dom_03

DOM的意义

DOM代表文档对象模型。文档指向以对象表示的HTML(XML)文档。(在javascript中,所有内容都只能表示为对象!)

这个模型是由浏览器创建的,它接受一个HTML文档并创建一个表示它的对象。我们可以用javascript访问这个对象。由于我们使用这个对象来操作HTML文档和构建我们自己的应用程序,所以DOM基本上是一个API。

DOM树

在JavaScript代码中,HTML文档表示为一个对象。从该文档中读取的所有数据也被保存为对象,彼此嵌套(因为就像我前面所说的,在JavaScript中,所有数据都只能表示为对象)。

所以,这基本上就是代码中DOM数据的物理排列:所有的东西都是作为对象排列的。但从逻辑上讲,它是一棵树。

DOM解析器

每个浏览器软件都有一个名为dom parser的程序,负责将HTML文档解析为dom。

详细了解文档对象模型(DOM)_html_04


将数据从HTML解析到DOM树

取一个简单的HTML文件。它有根元素。它的子元素是和,每个子元素都有自己的子元素。

因此,从本质上讲,浏览器读取HTML文档中的数据,类似于:

<html>
<head>
<meta/>
<link/>
</head>
<body>
<header>
<h1></h1>
<h2></h2>
</header>
<main>
<article>
<p></p>
<p></p>
<p></p>
</article>
</main>
<footer>
<div></div>
</footer>
</body>
</html>

然后,像这样将它们排列成一个DOM树:

详细了解文档对象模型(DOM)_重绘_05

DOM树中每个HTML元素(及其所属内容)的标签称为节点。根节点是的节点。

JavaScript中的DOM接口称为文档(因为它是HTML文档的表示)。因此,我们通过JavaScript中的文档接口访问HTML文档的DOM树。

我们不仅可以访问,还可以通过DOM操作HTML文档。我们可以向网页添加元素,删除并更新它们。每次我们更改或更新DOM树中的任何节点时,它都会渲染到网页上。

如何设计节点

我之前提到过,HTML文档中的每一段数据都保存为JavaScript中的一个对象。那么,如何将保存为对象的数据逻辑地排列为树呢

DOM树的节点具有某些特性或属性。几乎树中的每个节点都有一个父节点(它上面的节点)、子节点(它下面的节点)和兄弟节点(属于同一父节点的其他节点)。在一个节点的上面、下面和周围拥有这个族是使它成为树的一部分的条件。

每个节点的族信息都保存为表示该节点的对象中的属性。例如,children是一个节点的属性,它包含该节点的子元素列表,从而在逻辑上将其子元素排列在该节点下。

避免过度操作DOM

尽管我们发现更新DOM很有用(为了修改网页),但是别过度操作。

例如,您希望使用javascript更新网页上的div标签的颜色。您需要做的是访问相应的dom节点对象并修改color属性。这不应该影响树的其余部分(树中的其他节点)。

但是,如果要从树中删除节点或向其中添加节点,该怎么办?整个树可能需要重新渲染,删除节点或将节点添加到树中。这是一项昂贵的工作。完成这项工作需要时间和浏览器资源。

例如,假设您想向一个表中添加五行。对于每一行,当它的新节点被创建并添加到DOM时,树每次都被更新,总共添加了五个更新。

我们可以通过使用documentfragment接口来避免这种情况。把它想象成一个可以容纳所有五行并添加到树上的盒子。通过这种方式,将这五行添加为一个单独的数据块,而不是一个接一个地添加,从而在树中只进行一次更新。

这不仅在删除或添加元素时发生,而且调整元素的大小也会影响其他节点,因为调整大小的元素可能需要其周围的其他元素来调整其大小。因此,需要更新所有其他元素的对应节点,并根据新规则重绘HTML元素。

同样,当整个网页的布局受到影响时,可能会重新呈现该网页的一部分或全部。这一过程称为重绘。为了避免过度重绘,请确保不要过度更改DOM。对dom的更改并不是唯一会导致网页重绘的事情。根据浏览器的不同,其他因素也会对其产生影响

总结

把这些东西包装起来,DOM被可视化为一个由HTML文档中的所有元素组成的树。物理上(数字能得到的物理上的任何东西),它是一组嵌套的javascript对象,其中的属性和方法保存着信息,使逻辑上将它们排列到树中成为可能。

另请阅读:​​CSS对象模型(CSSOM)初学者指南​