DOM(Document Object Model,文档对象模型)允许我们用 JavaScript 来探查和操作 HTML 文档里的内容。它对于创建丰富性内容而言是必不可少的一组功能。

1. 理解文档对象模型

DOM 是一组对象的集合,这些对象代表了HTML文档里的各个元素。顾名思义,DOM就像一个模型,它由代表文档的众多对象组成。

先来个简单的HTML文档的例子:

<!DOCTYPE html>
<html>
<head>
<meta name="author" content="Luka" />
<meta name="description" content="A simple example" />
<title>Example</title>
</head>
<body>
<p>
你的特别不是因为你在创业,不是因为你进了牛企,不是因为你的牛offer,而是因为你就是你,坚信自己的特别,坚信自己的内心,勇敢做自己。
<span>IT DOESN'T MATTER WHERE YOU ARE, IT MATTERS WHO YOU ARE.</span>
</p>
<p>
15岁的时候再得到那个5岁的时候热爱的布娃娃,65岁的时候终于有钱买25岁的时候热爱的那条裙子,又有什么意义。
什么都可以从头再来,只有青春不能。
那么多事情,跟青春绑在一起就是美好,离开青春,就是傻冒。
</p>
</body>
</html>

从下图可以看到浏览器是如何显示上述示例HTML文档的:

作为显示HTML文档过程中的一个步骤,浏览器会解析HTML并创建一个模型。这个模型保存了各个HTML元素之间的层级关系(如下图所示),每个元素都由一个 JavaScript 对象表示。

你可以用DOM来获取文档信息,也可以对其进行修改。这是现代Web应用程序的基础。

模型里的每个对象都由若干个属性和方法。当你用它们来修改对象的状态时,浏览器会让这些改动反映到对应的HTML元素上,并更新文档。

所有代表元素的DOM对象都支持同一组基本功能:HTMLElement 对象和其定义的核心功能始终是可用的,无论对象代表何种元素都是如此。另外,某些对象会定义一些额外的功能。这些操作反映了特定HTML元素的独一无二的特性。文档模型里任何代表某个元素的对象都至少能支持HTMLElement 功能,其中一些还支持额外的功能。

不是所有可供使用的对象都代表了HTML元素。一些对象代表元素的集合,另一些则代表DOM自身的信息,当然还有Document这个镀锡,它是我们探索DOM的入口。

2. 理解 DOM Level和兼容性

DOM Level是标准化过程中的版本号,在大多数情况下应该忽略它们。

DOM 的标准化并不是完全成功的,每一个DOM Level都有描述它的标准和文档,但它们并没有完整地实现,浏览器只是简单的挑选了其中的有用功能,而忽略了其他的。更糟的是,已经实现的功能还存在某种程度的不一致性。

部分问题在于,DOM规范与HTML标准过去是分别开发的。HTML5试图通过包含一组必须实现的DOM核心功能来解决这个问题。然而这种做法尚未见效,碎片化仍然存在。

有多种方式可用来实现DOM功能的多变性。第一种方式是使用某个JavaScript库(比如jQuery),它消除了浏览器之间实现方式的差别。使用库的有点在于其一致性,但缺点是只能用库支持的那些功能。如果想突破原有功能的局限,就只能转回到直接操作DOM上,并重新面对之前的问题。

第二种是保守方式:只使用所知的被广泛支持的那些功能。这种方式一般来说是最明智的,不过它需要仔细而全面的测试。不仅如此,还必须测试新版的浏览器确保对这些功能的支持没有发生编号或者被移除。

测试DOM功能

第三张方式是测试与某一功能相关的DOM对象属性或方法是否存在。下面是一个简单的例子:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Example</title>
</head>
<body>
<p id="sentence">
<img src="imgs/apple.png" alt="apple" />
</p>
<script>
var images;
if(document.querySelectorAll){
images = document.querySelectorAll("#sentence > img");
}else{
images = document.getElementById("sentence").getElementsByTagName("img");
} for (var i = 0; i < images.length; i++){
images[i].style.border = "thick solid black";
images[i].style.padding = "4px";
}
</script>
</body>
</html>

此例中,脚本使用一条 if 语句来判断 document 对象是否定义了一个名为 querySelectorAll 的方法。如果这条语句的计算结果是 true,那么浏览器是支持这一功能的,我们就可以开始使用它。如果该语句的计算结果是 false,那么可以换一种方式来达到同样的目的。

谈到DOM时,经常看到的就是刚才这种建议,但它过于草率,没有指出其中的缺陷,而这些缺陷有可能很严重。

第一个缺陷在于,并不总是存在另一种方式能实现某个给定功能的效果。此例代码能顺利功能是因为测试的功能是其他函数的一种便利性加强形式,但情况并不总是如此。

第二个缺陷是只测试了该功能是否存在,而不是它的实现质量和一致性。许多功能(特别是新功能)需要多个版本的浏览器才能稳定下来并实现一致性。虽然这个问题不像以前那样严重,但也许很容易就遇到意料之外 的结果,因为依赖的浏览器功能实现方式存在差别。

第三个缺陷是必须测试每一种所依赖的功能。这么做需要耗费大量的精力,而且产生的代码充斥着无穷无尽的测试。这里并不是说它不是一种有用的测试,而是它存在缺陷,不应该取代恰当的测试。

来源:《HTML5权威指南》(《The Definitive Guide to HTML5》)

【使用 DOM】理解 DOM的更多相关文章

  1. 理解DOM事件流的三个阶段

    本文主要解决两个问题: 1.什么是事件流 2.DOM事件流的三个阶段 事件流之事件冒泡与事件捕获 在浏览器发展的过程中,开发团队遇到了一个问题.那就是页面中的哪一部分拥有特定的事件? 可以想象画在一张 ...

  2. 【温故而知新-Javascript】理解 DOM

    DOM(Document Object Model,文档对象模型)允许我们用 JavaScript 来探查和操作 HTML 文档里的内容.它对于创建丰富性内容而言是必不可少的一组功能. 1. 理解文档 ...

  3. Virtual DOM 虚拟DOM的理解(转)

    作者:戴嘉华 转载请注明出处并保留原文链接( #13 )和作者信息. 目录: 1 前言 2 对前端应用状态管理思考 3 Virtual DOM 算法 4 算法实现 4.1 步骤一:用JS对象模拟DOM ...

  4. javascript:理解DOM事件

    首先,此文不讨论繁琐细节,但是考虑到读者的心灵感受,本着以积极向上的心态,在此还是会列举示例说明. ​标题为理解DOM事件,那么在此拿一个简单的点击事件为例,希望大家看到这个例子后能触类旁通. DOM ...

  5. 深度理解DOM事件(实例)

    前言 通过如下两个实例来理解DOM事件 实例1--点击别处关闭浮层 onclick与addEventListener的区别 实例2--点击后颜色一层一个层出现的漂亮的彩虹圈 1  实例1--点击别处关 ...

  6. javascript学习 真正理解DOM脚本编程技术背后的思路和原则

    本文学习来源于<javascriptDOM编程艺术>仅作笔记 学会怎样才能利用DOM脚本编程技术以一种既方便自己更体贴用户的方式去充实和完善你们的网页. 循序渐进:从最核心的内容开始,逐步 ...

  7. javascript DOM和DOM操作的四种基本方法

    在了解了javascript的语言特性后,javascript真正大放光彩的地方来了——这就是javascript DOM Javascript DOM DOM(Document Object Mod ...

  8. 虚拟DOM Vitural DOM Tree

      提起Virtual DOM,总是给人一种高深莫测的感觉,大家都知道它比DOM快.那么Virtual DOM到底是何方神圣呢?在深入理解Virtual DOM之前,先让我们回顾一下DOM. 一.什么 ...

  9. React v16-alpha 从virtual dom 到 dom 源码简读

    一.物料准备 1.克隆react源码, github 地址:https://github.com/facebook/react.git 2.安装gulp 3.在react源码根目录下: $npm in ...

随机推荐

  1. svn merge详解

    svn merge详解 [OK] http://blog.163.com/lgh_2002/blog/static/4401752620106202710487/ Subversion的分支通常用于在 ...

  2. redux-saga call 和 fork的区别

    call 为阻塞调用, fork为非阻塞调用

  3. EF 创建数据库的策略 codefist加快效率!【not oringin!】

    今天去搜寻,ef创建数据库的策略有四种,区分还是和数据库里sql的创建的语句这些英文差不多一致. 一:数据库不存在时重新创建数据库 Database.SetInitializer<testCon ...

  4. zero(NOIP模拟赛 Round 4)

    题目描述 假设x=N!,那么x的末尾有多少个零呢? 输入 一行,一个整数N. 输出 输出只有一个整数,表示x末尾零的个数. 这道题目,我们看一看数据范围, 10^1000肯定是高精啦! 然后我们再想一 ...

  5. python--io

    import io # io模块里面主要使用StringIo和BytesIo # StringIo f = io.StringIO() # 像使用open函数创建文件一样,生成一个句柄 # 可以直接向 ...

  6. J.U.C并发框架源码阅读(十一)DelayQueue

    基于版本jdk1.7.0_80 java.util.concurrent.DelayQueue 代码如下 /* * ORACLE PROPRIETARY/CONFIDENTIAL. Use is su ...

  7. Wannafly挑战赛10 D 小H的询问(线段树)

    题目链接  Problem D 这个题类似 SPOJ GSS3 做过那个题之后其实就可以秒掉这题了. 考虑当前线段树维护的结点 在那道题的基础上,这个题要多维护几个东西,大概就是左端点的奇偶性,右端点 ...

  8. Xamarin XAML语言教程使用使用Progress属性设置当前进度

    Xamarin XAML语言教程使用使用Progress属性设置当前进度 开发者除了可以在XAML中使用Progress属性设置进度条的当前进度外,还可以在代码隐藏文件中使用Progress属性来设置 ...

  9. Java JVM:内存溢出(栈溢出,堆溢出,持久代溢出以及 nable to create native thread)

    转载自https://github.com/pzxwhc/MineKnowContainer/issues/25 包括:1. 栈溢出(StackOverflowError)2. 堆溢出(OutOfMe ...

  10. AtCoder - 4130 K-th Substring

    Problem Statement You are given a string s. Among the different substrings of s, print the K-th lexi ...