DOM是什么
DOM(文档对象模型)是Web前端里最基础、最常用的一个模型。例如,一个网页其实就是一个 HTML 文件,经过浏览器的解析,最终呈现在用户面前。HTML语言是由很多标签组成的,代码如下所示:
<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>程序员天天说的DOM到底是什么</title>
</head>
<body>
<h1>我的第一个标题</h1>
<p>我的第一个段落</p>
</body>
</html>
上述代码中,head和body是标签。这些标签不是随意摆放的,它们有自己的规则。首先,它们是嵌套的,一层套一层,比如html套 body,body又套h1。其次,每一层可以同时存在很多标签,比如 head 和 body 属于同一层,它们被外面的 html套着。这样的结构很像计算机里的文件夹。例如,“我的电脑”是最外层,里面套着C、D、E、F盘,每个盘里又有很多文件夹,文件夹里又有文件夹,逐个打开后才能看到具体的文件。
为什么要按照这种结构来组织呢?目的其实是方便解析和查询。解析的时候,从外向里循序渐进,好比按照图纸盖房子,先盖围墙,再盖走廊,最后才盖卧室。查询的时候,会遵循一条明确的路线,例如“D盘/文化交流/影视作品/给产品经理讲技术.avi”,一层一层地缩小范围,查找效率会非常高。所以,浏览器在解析HTML文档时,会把每个标签抽象成代码里的对象,按照这种层次分明的结构组织,这就是DOM。
如图1-2所示为数据结构里典型的“树”结构。程序员经常说的DOM树,其实就是这个意思。浏览器在解析 HTML 时,会在它的内部构建这样一棵 DOM 树,然后按照这棵树上的层次顺序解析每个标签。解析完成后,用户就看到了网页的内容。
图1-2
浏览器解析完HTML,就要开始解析HTML里的JavaScript代码。程序员可以通过 JavaScript代码实现一些动态的网页效果。例如,从服务器拉取一段数据来展示,或做一个酷炫的动画效果,都要用到DOM。
举个简单的例子(代码如下所示),想要在网页里显示一行字“this is from javascript”,首先要找到那个可以显示文字的标签。这是非常容易的,因为浏览器已经把DOM都交给JavaScript了。DOM里的对象,正好就是JavaScript语言里的对象。JavaScript可以通过下面的方法修改DOM树上的标签对象。
随着对前端知识学习的深入,读者会发现JavaScript操纵DOM是非常普遍的事情。例如,很多网页一开始加载出来的只是个架子,只显示出一个loading图标的转圈动画,只有等JavaScript从服务器上请求到真正的数据后操纵DOM来显示数据,才能看到内容,这就是典型的异步加载。以HTML 5的游戏为例,里面的人物要随着手指或鼠标运动,普遍的做法是通过JavaScript操纵DOM改变元素的位置来实现。可以说,DOM使得JavaScript在前端世界里几乎无所不能。
但是,有一点要注意:操纵DOM本身是一件效率非常低的事情。一个网页往往很复杂,浏览器构造出来的DOM树往往很庞大,有的甚至有几千个节点。在这么庞大的一棵树上频繁地改动,对浏览器(尤其是移动浏览器)来说是不小的工作量,稍不注意就会出现卡顿。
于是,有人发明了一种便捷的方法,叫作虚拟DOM。简单来说,就是用JavaScript模拟了一棵简单的DOM树,然后在这上面演练所有的DOM操作,等时机成熟时再把虚拟DOM树和真正的浏览器的DOM树做对比,算出差异,一次性地改变真正的DOM树。这两个步骤从整体上大大提高了JavaScript操纵DOM树的效率。