中国石凳联盟 登录注册

【转贴】利用DOM进行Web响应

rockage··3 回复·383 浏览

发表回复
程序员(使用后端应用程序)和 Web 程序员(编写 HTML、CSS 和 JavaScript)之间的分水岭是长久存在的。但是,Document Object Model (DOM) 弥补了这个裂缝,使得在后端使用 XML 同时在前端使用 HTML 切实可行,并成为极其有效的工具。在本文中,Brett McLaughlin 介绍了 Document Object Model,解释它在 Web 页面中的应用,并开始挖掘其在 JavaScript 中的用途。
  与许多 Web 程序员一样,您可能使用过 HTML。HTML 是程序员开始与 Web 页面打交道的方式HTML 通常是他们完成应用程序或站点前的最后一步——调整一些布局、颜色或样式。不过,虽然经常使用 HTML,但对于 HTML 转到浏览器呈现在屏幕上时到底发生了什么,人们普遍存在误解。在我分析您认为可能发生的事情及其可能错误的原因之前,我希望您对设计和服务 Web 页面时涉及的过程一清二楚:


  1. 一些人(通常是您!)在文本编辑器或 IDE 中创建 HTML。
  2. 然后您将 HTML 上载到 Web 服务器,例如 Apache HTTPD,并将其公开在 Internet 或 intranet 上。
  3. 用户用 Firefox 或 SafariA 等浏览器请求您的 Web 页面。
  4. 用户的浏览器向您的服务器请求 HTML。
  5. 浏览器将从服务器接收到的页面以图形和文本方式呈现用户看到并激活 Web 页面。


  这看起来非常基础,但事情很快会变得有趣起来。事实上,步骤 4 和步骤 5 之间发生的巨大数量的 “填充物(stuff)” 就是本文的焦点。术语 “填充物” 也十分适用,因为多数程序员从来没有真正考虑过当用户浏览器请求显示标记时到底在标记身上发生了什么。


  是否浏览器只是读取 HTML 中的文本并将其显示?
  CSS 呢?尤其是当 CSS 位于外部文件时。
  JavaScript 呢?它也通常位于外部文件中。
  浏览器如何处理这些项,如果将事件处理程序、函数和样式映射到该文本标记?


  实践证明,所有这些问题的答案都是 Document Object Model。因此,废话少说,直接研究 DOM。

  
Web 程序员和标记


  对于多数程序员,当 Web 浏览器开始时他们的工作就结束了。也就是说,将一个 HTML 文件放入 Web 浏览器的目录上后,您通常就认为它已经“完成”,而且(满怀希望地)认为再也不会考虑它!说到编写干净、组织良好的页面时,这也是一个伟大的目标希望您的标记跨浏览器、用各种版本的 CSS 和 JavaScript 显示它应该显示的内容,一点错都没有。

  问题是这种方法限制了程序员对浏览器中真正发生的事情的理解。更重要的是,它限制了您用客户端 JavaScript 动态更新、更改和重构 Web 页面的能力。摆脱这种限制,让您的 Web 站点拥有更大的交互性和创造性。

  
程序员做什么


  作为典型的 Web 程序员,您可能启动文本编辑和 IDE 后就开始输入 HTML、CSS 甚至 JavaScript。很容易认为这些标记、选择器和属性只是使站点正确显示而做的小小的任务。但是,在这一点上您需要拓展您的思路,要意识到您是在组织您的内容。不要担心我保证这不会变成关于标记美观、您必须如何认识到 Web 页面的真正潜力或其他任何元物质的讲座。您需要了解的是您在 Web 开发中到底是什么角色。

  说到页面的外观,顶多您只能提提建议。您提供 CSS 样式表时,用户可以覆盖您的样式选择。您提供字体大小时,用户浏览器可以为视障者更改这些大小,或者在大显示器(具有同等大的分辨率)上按比例缩小。甚至您选择的颜色和字体也受制于用户显示器和用户在其系统上安装的字体。虽然尽您所能来设计页面样式很不错,但这绝不是 您对 Web 页面的最大影响。

  您绝对控制的是 Web 页面的结构。您的标记不可更改,用户就不能乱弄他们的浏览器只能从您的 Web 服务器检索标记并显示它(虽然样式更符合用户的品味而不是您自己的品味)。但页面组织,不管是在该段落内还是在其他分区,都只由您单独决定。要是想实际更改您的页面(这是大多数 Ajax 应用程序所关注的),您操作的是页面的结构。尽管很容易更改一段文本的颜色,但在现有页面上添加文本或整个区段要难得多。不管用户如何设计该区段的样式,都是由您控制页面本身的组织。

  
标记做什么


  一旦意识到您的标记是真正与组织相关的,您就会对它另眼相看了。不会认为 h1 导致文本是大字号、黑色、粗体的,而会认为 h1 是标题。用户如何看待这个问题以及他们是使用您的 CSS、他们自己的 CSS 还是这两者的组合,这是次要的考虑事项。相反,要意识到只有标记才能提供这种级别的组织p 指明文本在段落内,img 表示图像,div 将页面分成区段,等等。

  还应该清楚,样式和行为(事件处理程序和 JavaScript)是在事后 应用于该组织的。标记就绪以后才能对其进行操作或设计样式。所以,正如您可以将 CSS 保存在 HTML 的外部文件中一样,标记的组织与其样式、格式和行为是分离的。虽然您肯定可以用 JavaScript 更改元素或文本的样式,但实际更改您的标记所布置的组织却更加有趣。

  只要牢记您的标记只为您的页面提供组织、框架,您就能立于不败之地。再前进一小步,您就会明白浏览器是如何接受所有的文本组织并将其转变为超级有趣的一些东西的,即一组对象,其中每个对象都可被更改、添加或删除。


文本标记的优点


  在讨论 Web 浏览器之前,值得考虑一下为什么纯文本绝对 是存储 HTML 的最佳选择。不考虑优缺点,只是回忆一下在每次查看页面时 HTML 是通过网络发送到 Web 浏览器的(为了简洁,不考虑高速缓存等)。真是再没有比传递文本再有效的方法了。二进制对象、页面图形表示、重新组织的标记块等等,所有这一切都比纯文本文件通过网络传递要更困难。

  此外,浏览器也为此增光添彩。今天的浏览器允许用户更改文本大小、按比例伸缩图像、下载页面的 CSS 或 JavaScript(大多数情况),甚至更多,这完全排除了将任何类型的页面图形表示发送到浏览器上。但是,浏览器需要原 HTML,这样它才能在浏览器中对页面应用任何处理,而不是信任浏览器去处理该任务。同样地,将 CSS 从 JavaScript 分离和将 CSS 从 HTML 标记分离要求一种容易分离的格式。文本文件又一次成为该任务的最好方法。

  最后但同样重要的一点是,记住,新标准(比如 HTML 4.01 与 XHTML 1.0 和 1.1)承诺将内容(页面中的数据)与表示和样式(通常由 CSS 应用)分离。如果程序员要将 HTML 与 CSS 分离,然后强制浏览器检索粘结页面各部分的一些页面表示,这会失去这些标准的多数优点。保持这些部分到达浏览器时都一直分离使得浏览器在从服务器获取 HTML 时有了前所未有的灵活性。

  
进一步了解 Web 浏览器


  对于一些 Web 程序员来说,在前文阅读到的所有内容可能是对您在 Web 开发过程中角色的滑稽讲述。但说到浏览器的行为,许多最能干的 Web 设计人员和开发人员通常都没有意识到 “内幕” 的实际状况。我将在本节重点进行讲述。不要担心,代码很快就到,但是要克制您编码的急躁心情,因为真正了解 Web 浏览器的确切行为对于您的代码正确工作是非常关键的。

  
文本标记的缺点


  正如文本标记对于设计人员和页面创建者具有惊人的优点之外,它对于浏览器也具有相当出奇的缺点。具体来说,浏览器很难直接将文本标记可视地表示给用户(详细信息请参阅 有关标记的一些其他想法)。考虑下列常见的浏览器任务:


  基于元素类型、类、ID 及其在 HTML 文档中的位置,将 CSS 样式(通常来自外部文件中的多个样式表)应用于标记。
  基于 JavaScript 代码(通常位于外部文件)将样式和格式应用于 HTML 文档的不同部分。
  基于 JavaScript 代码更改表单字段的值。
  基于 JavaScript 代码,支持可视效果,比如图像翻转和图像交换。


  复杂性并不在于编码这些任务其中每件事都是相当容易的。复杂性来自实际实现请求动作的浏览器。如果标记存储为文本,比如,想要在 center-text 类的 p 元素中输入文本 (text-align: center),如何实现呢?


  将内联样式添加到文本吗?
  将样式应用到浏览器中的 HTML 文本,并只保持内容居中或不居中?
  应用无样式的 HTML,然后事后应用格式?


  这些非常困难的问题是如今很少有人编写浏览器的原因。(编写浏览器的人应该接受最由衷的感谢)

  无疑,纯文本不是存储浏览器 HTML 的好办法,尽管文本是获取页面标记最好的解决方案。如果加上 JavaScript 更改 页面结构的能力,事情就变得有些微妙了。浏览器应该将修改过的结构重新写入磁盘吗?如何才能保持文档的最新版本呢?

  无疑,文本不是答案。它难以修改,为其应用样式和行为很困难,与今天 Web 页面的动态本质在根本上相去甚远。


求助于树视图


  这个问题的答案(至少是由当今 Web 浏览器选择的答案)是使用树结构来表示 HTML。参见 清单 1,这是一个表示为本文标记的相当简单又无聊的 HTML 页面。

  清单 1. 文本标记中的简单 HTML 页面





html
head
titleTrees, trees, everywhere/title
/head
body
h1Trees, trees, everywhere/h1
pWelcome to a emreally/em boring page./p
div
Come again soon.
img src="come-again.gif" /
/div
/body
/html





  浏览器接受该页面并将之转换为树形结构,如图 1 所示。




  图 1. 清单 1 的树视图

  为了保持本文的进度,我做了少许简化。DOM 或 XML 方面的专家会意识到空白对于文档文本在 Web 浏览器树结构中表示和分解方式的影响。肤浅的了解只会使事情变得模棱两可,所以如果想弄清空白的影响,那最好不过了如果不想的话,那可以继续读下去,不要考虑它。当它成为问题时,那时您就会明白您需要的一切。

  除了实际的树背景之外,可能会首先注意到树中的一切是以最外层的 HTML 包含元素,即 html 元素开始的。使用树的比喻,这叫做根元素。所以即使这是树的底层,当您查看并分析树的时候,我也通常以此开始。如果它确实奏效,您可以将整个树颠倒一下,但这确实有些拓展了树的比喻。

  从根流出的线表示不同标记部分之间的关系。head 和 body 元素是 html 根元素的孩子title 是 head 的孩子,而文本 “Trees, trees, everywhere” 是 title 的孩子。整个树就这样组织下去,直到浏览器获得与 图 1 类似的结构。


一些附加术语


  为了沿用树的比喻,head 和 body 被叫做 html 的分支(branches)。叫分支是因为它们有自己的孩子。当到达树的末端时,您将进入主要的文本,比如 “Trees, trees, everywhere” 和 “really”这些通常称为叶子,因为它们没有自己的孩子。您不需要记住所有这些术语,当您试图弄清楚特定术语的意思时,只要想像一下树结构就容易多了。

  
对象的值


  既然了解了一些基本的术语,现在应该关注一下其中包含元素名称和文本的小矩形了(图 1)。每个矩形是一个对象浏览器在其中解决一些文本问题。通过使用对象来表示 HTML 文档的每一部分,可以很容易地更改组织、应用样式、允许 JavaScript 访问文档,等等。

  
对象类型和属性


  标记的每个可能类型都有自己的对象类型。例如,HTML 中的元素用 Element 对象类型表示。文档中的文本用 Text 类型表示,属性用 Attribute 类型表示,以此类推。

  所以 Web 浏览器不仅可以使用对象模型来表示文档(从而避免了处理静态文本),还可以用对象类型立即辨别出某事物是什么。HTML 文档被解析并转换为对象集合,如 图 1 所示,然后尖括号和转义序列(例如,使用 表示 ,使用 表示 )等事物不再是问题了。这就使得浏览器的工作(至少在解析输入 HTML 之后)变得更容易。弄清某事物究竟是元素还是属性并确定如何处理该类型的对象,这些操作都十分简单了。

  通过使用对象,Web 浏览器可以更改这些对象的属性。例如,每个元素对象具有一个父元素和一系列子元素。所以添加新的子元素或文本只需要向元素的子元素列表中添加一个新的子元素。这些对象还具有 style 属性,所以快速更改元素或文本段的样式非常简单。例如,要使用 JavaScript 更改 div 的高度,如下所示:




  someDiv.style.height = "300px"




  换句话说,Web 浏览器使用对象属性可以非常容易地更改树的外观和结构。将之比作浏览器在内部将页面表示为文本时必须进行的复杂事情,每次更改属性或结构都需要浏览器重新编写静态文件、重新解析并在屏幕上重新显示。有了对象,所有这一切都解决了。

  现在,花点时间展开一些 HTML 文档并用树将其勾画出来。尽管这看起来是个不寻常的请求(尤其是在包含极少代码的这样一篇文章中),如果您希望能够操纵这些树,那么需要熟悉它们的结构。

  在这个过程中,可能会发现一些古怪的事情。比如,考虑下列情况:


  属性发生了什么?
  分解为元素(比如 em 和 b)的文本呢?
  结构不正确(比如当缺少结束 p 标记时)的 HTML 呢?


  一旦熟悉这些问题之后,就能更好地理解下面几节了。

  
严格有时是好事


  如果尝试刚提到的练习 I,您可能会发现标记的树视图中存在一些潜在问题(如果不练习的话,那就听我说吧!)。事实上,在 清单 1 和 图 1 中就会发现一些问题,首先看 p 元素是如何分解的。如果您问通常的 Web 开发人员 “p 元素的文本内容是什么”,最常见的答案将是 “Welcome to a really boring Web page.”。如果将之与图 1 做比较,将会发现这个答案(虽然合乎逻辑)是根本不正确的。

  实际上,p 元素具有三个 不同的子对象,其中没有一个包含完整的 “Welcome to a really boring Web page.” 文本。您会发现文本的一部分,比如 “Welcome to a ” 和 “ boring Web page”,但不是全部。为了理解这一点,记住标记中的任何内容都必须转换为某种类型的对象。

  此外,顺序无关紧要!如果浏览器显示正确的对象,但显示顺序与您在 HTML 中提供的顺序不同,那么您能想像出用户将如何响应 Web 浏览器吗?段落夹在页面标题和文章标题中间,而这不是您自己组织文档时的样式呢?很显然,浏览器必须保持元素和文本的顺序。

  在本例中,p 元素有三个不同部分:


  em 元素之前的文本
  em 元素本身
  em 元素之后的文本


  如果将该顺序打乱,可能会把重点放在文本的错误部分。为了保持一切正常,p 元素有三个子对象,其顺序是在 清单 1 的 HTML 中显示的顺序。而且,重点文本 “really” 不是p 的子元素而是 p 的子元素 em 的子元素。

  理解这一概念非常重要。尽管 “really” 文本将可能与其他 p 元素文本一起显示,但它仍是 em 元素的直接子元素。它可以具有与其他 p 文本不同的格式,而且可以独立于其他文本到处移动。

  要将之牢记在心,试着用图表示清单 2 和 3 中的 HTML,确保文本具有正确的父元素(而不管文本最终会如何显示在屏幕上)。

清单 2. 带有巧妙元素嵌套的标记





html
head
titleThis is a little tricky/title
/head
body
h1Pay uclose/u attention, OK?/h1
div
pThis p really isnt emnecessary/em, but it makes the
span id="bold-text"structure iand/i the organization/span
of the page easier to keep up with./p
/div
/body
/html





  清单 3. 更巧妙的元素嵌套





html
head
titleTrickier nesting, still/title
/head
body
div id="main-body"
div id="contents"
table
trthSteps/ththProcess/th/tr
trtd1/tdtdFigure out the emroot element/em./td/tr
trtd2/tdtdDeal with the span id="code"head/span first,
as its usually easy./td/tr
trtd3/tdtdWork through the span id="code"body/span.
Just emtake your time/em./td/tr
/table
/div
div id="closing"
This link is emnot/em active, but if it were, the answers
to this a href="answers.html"img src="exercise.gif" //a would
be there. But emdo the exercise anyway!/em
/div
/div
/body
/html





  在本文末的 GIF 文件 图 2 中的 tricky-solution.gif 和 图 3 中的 trickier-solution.gif 中将会找到这些练习的答案。不要偷看,先花些时间自动解答一下。这样能帮助您理解组织树时应用的规则有多么严格,并真正帮助您掌握 HTML 及其树结构。

  
属性呢?


  当您试图弄清楚如何处理属性时,是否遇到一些问题呢?前已提及,属性确实具有自己的对象类型,但属性确实不是显示它的元素的子元素,嵌套元素和文本不在同一属性 “级别”,您将注意到,清单 2 和 3 中练习的答案没有显示属性。

  属性事实上存储在浏览器使用的对象模型中,但它们有一些特殊情况。每个元素都有可用属性的列表,且与子对象列表是分离的。所以 div 元素可能有一个包含属性 “id” 和另一个属性 “class” 的列表。

  记住,元素的属性必须具有惟一的名称,也就是说,一个元素不能有两个 “id” 或两个 “class” 属性。这使得列表易于维护和访问。在下一篇文章将会看到,您可以简单调用诸如 getAttribute("id") 的方法来按名称获取属性的值。还可以用相似的方法调用来添加属性或设置(重置)现有属性的值。

  值得指出的是,属性名的惟一性使得该列表不同于子对象列表。p 元素可以有多个 em 元素,所以子对象列表可以包含多个重复项。尽管子项列表和属性列表的操作方式相似,但一个可以包含重复项(对象的子项),而一个不能(元素对象的属性)。最后,只有元素具有属性,所以文本对象没有用于存储属性的附加列表。

  
凌乱的 HTML


  
在继续之前,谈到浏览器如何将标记转换为树表示,还有一个主题值得探讨,即浏览器如何处理不是格式良好的标记。格式良好 是 XML 广泛使用的一个术语,有两个基本意思:




每个开始标记都有一个与之匹配的结束标记。所以每个 p 在文档中与 /p 匹配,每个 div 与 /div 匹配,等等。


最里面的开始标记与最里面的结束标记相匹配,然后次里面的开始标记与次里面的结束标记相匹配,依此类推。所以 bibold and italics/b/i 是不合法的,因为最里面的开始标记 i 与最里面的结束标记 b 匹配不当。要使之格式良好,要么 切换开始标记顺序,要么 切换结束标记顺序。(如果两者都切换,则仍会出现问题)。




深入研究这两条规则。这两条规则不仅简化了文档的组织,还消除了不定性。是否应先应用粗体后应用斜体?或恰恰相反?如果觉得这种顺序和不定性不是大问题,那么请记住,CSS 允许规则覆盖其他规则,所以,例如,如果 b 元素中文本的字体不同于 i 元素中的字体,则格式的应用顺序将变得非常重要。因此,HTML 的格式良好性有着举足轻重的作用。



如果浏览器收到了不是格式良好的文档,它只会尽力而为。得到的树结构在最好情况下将是作者希望的原始页面的近似,最坏情况下将面目全非。如果您曾将页面加载到浏览器中后看到完全出乎意料的结果,您可能在看到浏览器结果时会猜想您的结构应该如何,并沮丧地继续工作。当然,搞定这个问题相当简单:确保文档是格式良好的!如果不清楚如何编写标准化的 HTML,请咨询 参考资料 获得帮助。








DOM 简介



到目前为止,您已经知道浏览器将 Web 页面转换为对象表示,可能您甚至会猜想,对象表示是 DOM 树。DOM 表示 Document Object Model,是一个规范,可从 World Wide Web Consortium (W3C) 获得(您可以参阅 参考资料 中的一些 DOM 相关链接)。



但更重要的是,DOM 定义了对象的类型和属性,从而允许浏览器表示标记代码中。




文档对象




首先,需要访问对象模型本身。这非常容易;要在运行于 Web 页面上的任何 JavaScript 代码中使用内置 document 变量,可以编写如下代码:






var domTree = document




当然,该代码本身没什么用,但它演示了每个 Web 浏览器使得 document 对象可用于 JavaScript 代码,并演示了对象表示标记的完整树(图 1)。


每项都是一个节点


显然,document 对象很重要,但这只是开始。在进一步深入之前,需要学习另一个术语:节点。您已经知道标记的每个部分都由一个对象表示,但它不只是一个任意的对象,它是特定类型的对象,一个 DOM 节点。更特定的类型,比如文本、元素和属性,都继承自这个基本的节点类型。所以可以有文本节点、元素节点和属性节点。

如果已经有很多 JavaScript 编程经验,那您可能已经在使用 DOM 代码了。如果到目前为止您一直在跟踪本 Ajax 系列,那么现在您一定 使用 DOM 代码有一段时间了。例如,代码行 var number = document.getElementById("phone").value 使用 DOM 查找特定元素,然后检索该元素的值(在本例中是一个表单字段)。所以即使您没有意识到这一点,但您每次将 document 键入 JavaScript 代码时都会使用 DOM。

详细解释已经学过的术语,DOM 树是对象的树,但更具体地说,它是节点 对象的树。在 Ajax 应用程序中或任何其他 JavaScript 中,可以使用这些节点产生下列效果,比如移除元素及其内容,突出显示特定文本,或添加新图像元素。因为都发生在客户端(运行在 Web 浏览器中的代码),所以这些效果立即发生,而不与服务器通信。最终结果通常是应用程序感觉起来响应更快,因为当请求转向服务器时以及解释响应时,Web 页面上的内容更改不会出现长时间的停顿。

在多数编程语言中,需要学习每种节点类型的实际对象名称,学习可用的属性,并弄清楚类型和强制转换;但在 JavaScript 中这都不是必需的。您可以只创建一个变量,并为它分配您希望的对象(正如您已经看到的):




var domTree = document
var phoneNumberElement = document.getElementById("phone")
var phoneNumber = phoneNumberElement.value




没有类型,JavaScript 根据需要创建变量并为其分配正确的类型。结果,从 JavaScript 中使用 DOM 变得微不足道(将来有一篇文章会专门讲述与 XML 相关的 DOM,那时将更加巧妙)。


结束语


在这里,我要给您留一点悬念。显然,这并非是对 DOM 完全详尽的说明;事实上,本文不过是 DOM 的简介。DOM 的内容要远远多于我今天介绍的这些!

此时,深入了解 DOM 将十分简单,比如详细设计如何在 DOM 树中移动、获得元素和文本的值、遍历节点列表,等等,但这可能会让您有这种印象,即 DOM 是关于代码的,而事实上并非如此。

而且不要忘了,这里有清单 2 和 3 的答案,其中还包含了示例代码!

图 2. 清单 2 的答案




图 3. 清单 3 的答案





点赞0 收藏

掌握 Ajax 之操纵 DOM之一
------------------------------------------------
发布时间:2006-05-11 15:05:36 作者:Brett McLaughlin 出处:techtarget 语言:中文 阅读次数:555次


  上一篇中 Brett 介绍了文档对象模型(DOM),它的元素在幕后定义了 Web 页面。这一期文章中他将进一步探讨 DOM。了解如何创建、 删除和修改 DOM 树的各个部分,了解如何实现网页的即时更新!(注意,下面的讨论以上一篇文章 “利用 DOM 进行 Web 响应” 为基础, 如果没有阅读过那一期,请在继续阅读之前首先阅读上一篇文章。)

  如果阅读过本系列的上一篇文章,那么您就非常清楚当 Web 浏览器显示网页时幕后发生的一切了。当 HTML 或为页面定义的 CSS 发送 给 Web 浏览器时,网页被从文本转化成对象模型。无论代码简单或复杂,集中到一个文件还是分散到多个文件,都是如此。然后浏览器直接使 用对象模型而不是您提供的文本文件。浏览器使用的模型称为文档对象模型(Document Object Model,DOM)。它连接表示文档中元素、属性和 文本的对象。HTML 和 CSS 中所有的样式、值、甚至大部分空格都合并到该对象模型中。给定网页的具体模型称为该页面的 DOM 树。

  了解什么是 DOM 树,以及知道它如何表示 HTML 和 CSS 仅仅是控制 Web 页面的第一步。接下来还需要了解如何处理 Web 页面的 DOM 树。比方说,如果向 DOM 树中增加一个元素,这个元素就会立即出现在用户的 Web 浏览器中 —— 不需要重新加载页面。从 DOM 树中删除一 些文本,那些文本就会从用户屏幕上消失。可以通过 DOM 修改用户界面或者与用户界面交互,这样就提供了很强的编程能力和灵活性。一旦学 会了如何处理 DOM 树,您就向实现丰富的、交互式动态网站迈出了一大步。 

  跨浏览器、跨语言

  文档对象模型是一种 W3C 标准。因此,所有现代 Web 浏览器都支持 DOM —— 至少在一定程度上支持。虽然不同的浏览器有一些区别 ,但如果使用 DOM 核心功能并注意少数特殊情况和例外,DOM 代码就能以同样的方式用于任何浏览器。修改 Opera 网页的代码同样能用于 Apple"s Safari、Firefox、Microsoft Internet Explorer 和 Mozilla。

  DOM 也是一种跨语言 的规范,换句话说,大多数主流编程语言都能使用它。W3C 为 DOM 定义了几种语言绑定。一种语言绑定就是为特 定语言定义的让您使用 DOM 的 API。比如,可以使用为 C、Java 和 JavaScript 定义的 DOM 语言绑定。因此可以从这些语言中使用 DOM。还 有几种用于其他语言的语言绑定,尽管很多是由 W3C 以外的第三方定义的。

  本系列文章主要讨论 JavaScript 的 DOM 绑定。这是因为多数异步应用程序开发都需要编写在 Web 浏览器中运行的 JavaScript 代码 。使用 JavaScript 和 DOM 可以即时修改用户界面、响应用户事件和输入等等 —— 使用的完全是标准的 JavaScript。

  总之,建议您也尝试一下其他语言中的 DOM 绑定。比如,使用 Java 语言绑定不仅能处理 HTML 还可处理 XML,这些内容将在以后的 文章中讨论。因此本文介绍的技术还可用于 HTML 之外的其他语言,客户端 JavaScript 之外的其他环境。

  节点的概念

  节点是 DOM 中最基本的对象类型。实际上,您将在本文中看到,基本上 DOM 定义的其他所有对象都是节点对象的扩展。但是在深入分 析语义之前,必须了解节点所代表的概念,然后再学习节点的具体属性和方法就非常简单了。

  在 DOM 树中,基本上一切都是节点。每个元素在最底层上都是 DOM 树中的节点。每个属性都是节点。每段文本都是节点。甚至注释、 特殊字符(如版权符号 )、DOCTYPE 声明(如果 HTML 或者 XHTML 中有的话)全都是节点。因此在讨论这些具体的类型之前必须清楚地把 握什么是节点。

  节点是……

  用最简单的话说,DOM 树中的任何事物都是节点 。之所以用 “事物” 这个模糊的字眼,是因为只能明确到这个程度。比如 HTML 中 的元素(如 img)和 HTML 中的文本片段(如 “Scroll down for more details”)没有多少明显的相似之处。但这是因为您考虑的可能是每种类 型的功能,关注的是它们的不同点。

  但是如果从另一个角度观察,DOM 树中的每个元素和每段文本都有一个父亲,这个父节点可能是另一个元素(比如嵌套在 p 元素中的 img)的孩子,或者 DOM 树中的顶层元素(这是每个文档中都出现一次的特殊情况,即使用 html 元素的地方)。另外,元素和文本都有一个类型 。显然,元素的类型就是元素,文本的类型就是文本。每个节点还有某种定义明确的结构:下面还有节点(如子元素)吗?有兄弟节点(与元素或文 本 “相邻的” 节点)吗?每个节点属于哪个文档?

  显然,大部分内容听起来很抽象。实际上,说一个元素的类型是元素似乎有点冒傻气。但是要真正认识到将节点作为通用对象类型的价 值,必须抽象一点来思考。

  通用节点类型

  DOM 代码中最常用的任务就是在页面的 DOM 树中导航。比方说,可以通过其 “id” 属性定位一个 form,然后开始处理那个 form 中 内嵌的元素和文本。其中可能包含文字说明、输入字段的标签、真正的 input 元素,以及其他 HTML 元素(如 img)和链接(a 元素)。如果元素 和文本是完全不同的类型,就必须为每种类型编写完全不同的代码。

  如果使用一种通用节点类型情况就不同了。这时候只需要从一个节点移动到另一个节点,只有当需要对元素或文本作某种特殊处理时才 需要考虑节点的类型。如果仅仅在 DOM 树中移动,就可以与其他节点类型一样用同样的操作移动到元素的父节点或者子节点。只有当需要某种 节点类型的特殊性质时,如元素的属性,才需要对节点类型作专门处理。将 DOM 树中的所有对象都看作节点可以简化操作。记住这一点之后, 接下来我们将具体看看 DOM 节点构造应该提供什么,首先从属性和方法开始。

  节点的属性

  使用 DOM 节点时需要一些属性和方法,因此我们首先来讨论节点的属性和方法。DOM 节点的属性主要有:

  nodeName 报告节点的名称(详见下述)。
  nodeValue 提供节点的 “值”(详见后述)。
  parentNode 返回节点的父节点。记住,每个元素、属性和文本都有一个父节点。
  childNodes 是节点的孩子节点列表。对于 HTML,该列表仅对元素有意义,文本节点和属性节点都没有孩子。
  firstChild 仅仅是 childNodes 列表中第一个节点的快捷方式。
  lastChild 是另一种快捷方式,表示 childNodes 列表中的最后一个节点。
  previousSibling 返回当前节点之前 的节点。换句话说,它返回当前节点的父节点的 childNodes 列表中位于该节点前面的那个节点 (如果感到迷惑,重新读前面一句)。
  nextSibling 类似于 previousSibling 属性,返回父节点的 childNodes 列表中的下一个节点。
  attributes 仅用于元素节点,返回元素的属性列表。
  其他少数几种属性实际上仅用于更一般的 XML 文档,在处理基于 HTML 的网页时没有多少用处。

  不常用的属性

  上述大部分属性的意义都很明确,除了 nodeName 和 nodeValue 属性以外。我们不是简单地解释这两个属性,而是提出两个奇怪的问 题:文本节点的 nodeName 应该是什么?类似地,元素的 nodeValue 应该是什么?

  如果这些问题难住了您,那么您就已经了解了这些属性固有的含糊性。nodeName 和 nodeValue 实际上并非适用于所有 节点类型(节点 的其他少数几个属性也是如此)。这就说明了一个重要概念:任何这些属性都可能返回空值(有时候在 JavaScript 中称为 “未定义”)。比方说 ,文本节点的 nodeName 属性是空值(或者在一些浏览器中称为 “未定义”),因为文本节点没有名称。如您所料,nodeValue 返回节点的文本 。

  类似地,元素有 nodeName,即元素名,但元素的 nodeValue 属性值总是空。属性同时具有 nodeName 和 nodeValue。下一节我还将讨 论这些单独的类型,但是因为这些属性是每个节点的一部分,因此在这里有必要提一提。

  现在看看 清单 1,它用到了一些节点属性。

  清单 1. 使用 DOM 中的节点属性

// These first two lines get the DOM tree for the current Web page,
// and then the html element for that DOM tree
var myDocument = document
var htmlElement = myDocument.documentElement

// What"s the name of the html element? "html"
alert("The root element of the page is " + htmlElement.nodeName)

// Look for the head element
var headElement = htmlElement.getElementsByTagName("head")
if (headElement != null) {
alert("We found the head element, named " + headElement.nodeName)
// Print out the title of the page
var titleElement = headElement.getElementsByTagName("title")
if (titleElement != null) {
// The text will be the first child node of the title element
var titleText = titleElement.firstChild
// We can get the text of the text node with nodeValue
alert("The page title is "" + titleText.nodeValue + """)
}

// After head is body
var bodyElement = headElement.nextSibling
while (bodyElement.nodeName.toLowerCase() != "body") {
bodyElement = bodyElement.nextSibling
}

// We found the body element...

// We"ll do more when we know some methods on the nodes.
}



节点方法

接下来看看所有节点都具有的方法(与节点属性一样,我省略了实 际上不适用于多数 HTML DOM 操作的少数方法):

insertBefore(newChild, referenceNode) 将 newChild 节点插入到 referenceNode 之前。记住,应 该对 newChild 的目标父节点调用该方法。
replaceChild(newChild, oldChild) 用 newChild 节点替换 oldChild 节点。
removeChild(oldChild) 从运行该方法的节点中删除 oldChild 节点。
appendChild(newChild) 将 newChild 添加到运行该函数的节 点之中。newChild 被添加到目标节点孩子列表中的末端。
hasChildNodes() 在调用该方法的节点有孩子时则返回 true,否则返回 false 。
hasAttributes() 在调用该方法的节点有属性时则返回 true,否则返回 false。

注意,大部分情况下所有这些方法处理的都是节点的孩子。这是它 们的主要用途。如果仅仅想获取文本节点值或者元素名,则不需要调用这些方法,使用节点属性就可以了。清单 2 在 清单 1 的基础上增加了 方法使用。

清单 2. 使用 DOM 中的节点方法

// These first two lines get the DOM tree for the curr ent Web page,
// and then the html element for that DOM tree
var myDocument = document
var htmlElement = myDocument.documentElement
// What"s the name of the html element? "html"
alert ("The root element of the page is " + htmlElement.nodeName)
// Look for the head element
var headElement = htmlElement.getElementsByTagName("head")
if (headElement != null) {
alert ("We found the head element, named " + headElement.nodeName)
// Print out the title of the page
var titleElement = headElement.getElementsByTagName("title")
if (titleElement != null) {
// The text will be the first childnb spnode of the title element
var titleText = titleElement.firstChild
// We can get the text of the tex t node with nodeValue
alert ("The page title is "" + titleText.nodeValue + """)
}
// After head is body
var bodyElement = headElement.nextSibling
while (bodyElement.nodeName.toLowerCase() != "body") {
bodyElement = bodyElement.nextSibling
}
// We found the body element...
// Remove all the top- level img elements in the body
if (bodyElement.hasChildNodes()) {
for (i=0 ibodyElement.childNodes.length i++) {
var currentNode = bodyElement.childNodes
if (currentNode.nodeName.toLowerCase() == "img") {
bodyElement.removeChild(currentNode)
}
}
}
}

测试一下!

目前虽然只看到了两个例子,清单 1 和 2,不过通过这两个例子您应该能够了解使用 DOM 树能够做什 么。如果要尝试一下这些代码,只需要将 清单 3 拖入一个 HTML 文件并保存,然后用 Web 浏览器打开。

清单 3. 包含使用 DOM 的 JavaScript 代码的 HTML 文件

html
head
titleJavaScript and the DOM/title
script language="JavaScript"
function test() {
// These first two lines get the DOM tree for t he current Web page,
// and then the html element for that DOM tree
var myDocument = document
var htmlElement = myDocument.documentElement
// What"s the name of the html element? "html"
alert ("The root element of the page is " + htmlElement.nodeName)
// Look for the head element
var headElement = htmlElement.getElementsByTagName("head")
if (headElement != null) {
alert ("We found the head element, named " + headElement.nodeName)
// Print out the title of the page
var titleElement = headElement.getElementsByTagName("title")
if (titleElement != null) {
// The text will be the first childnb spnode of the title element
var titleText = titleElement.firstChild
// We can get the text of the tex t node with nodeValue
alert ("The page title is "" + titleText.nodeValue + """)
}
// After head is body
var bodyElement = headElement.nextSibling
while (bodyElement.nodeName.toLowerCase() != "body") {
bodyElement = bodyElement.nextSibling
}
// We found the body element...
// Remove all the top- level img elements in the body
if (bodyElement.hasChildNodes()) {
for (i=0 ibodyElement.childNodes.length i++) {
var currentNode = bodyElement.childNodes
if (currentNode.nodeName.toLowerCase() == "img") {
bodyElement.removeChild(currentNode)
}
}
}
}
}
/script
/head
body
pJavaScript and DOM are a perfect match.
You can read more in iHead Rush Ajax/i. lt/p
img src="
http://www.headfirstlabs.com/Images/hraj_cover-150.jpg
" /
input type="button" value="Test me!" onClick="test()" /
/body
/html


  将该页面加载到浏览器后,可以看到类似 图 1 所示的画面。



点赞0 收藏

API 设计问题

再看一看各种节点提供的属性和方法。对于那些熟悉面向对象(OO)编程的人来说,它们说明了 DOM 的一个重要特点:DOM 并非完全面向对象的 API。首先,很多情况下要直接使用对象的属性而不是调用节点对象的方法。比方说,没有 getNodeName() 方法,而要直接使用 nodeName 属性。因此节点对象(以及其他 DOM 对象)通过属性而不是函数公开了大量数据。

其次,如果习惯于使用重载对象和面向对象的 API,特别是 Java 和 C++ 这样的语言,就会发现 DOM 中的对象和方法命名有点奇怪。DOM 必须能用于 C、Java 和 JavaScript(这只是其中的几种语言),因此 API 设计作了一些折衷。比如,NamedNodeMap 方法有两种不同的形式:

getNamedItem(String name)
getNamedItemNS(Node node)
对于 OO 程序员来说这看起来非常奇怪。两个方法目的相同,只不过一个使用 String 参数而另一个使用 Node 参数。多数 OO API 中对这两种版本都会使用相同的方法名。运行代码的虚拟机将根据传递给方法的对象类型决定运行哪个方法。

问题在于 JavaScript 不支持这种称为方法重载 的技术。换句话说,JavaScript 要求每个方法或函数使用不同的名称。因此,如果有了一个名为 getNamedItem() 的接受字符串参数的方法,就不能再有另一个方法或函数也命名为 getNamedItem(),即使这个方法的参数类型不同(或者完全不同的一组参数)。如果这样做,JavaScript 将报告错误,代码不会按照预期的方式执行。

从根本上说,DOM 有意识地避开了方法重载和其他 OO 编程技术。这是为了保证该 API 能够用于多种语言,包括那些不支持 OO 编程技术的语言。后果不过是要求您多记住一些方法名而已。好处是可以在任何语言中学习 DOM,比如 Java,并清楚同样的方法名和编码结构也能用于具有 DOM 实现的其他语言,如 JavaScript。

让程序员小心谨慎

如果深入研究 API 设计或者仅仅非常关注 API 设计,您可能会问:“为何节点类型的属性不能适用于所有节点?” 这是一个很好的问题,问题的答案与政治及决策关系更密切,而非技术原因。简单地说,答案就是,“谁知道!但有点令人恼火,不是吗?”

属性 nodeName 意味着允许每种类型的节点都有一个名字,但是很多情况下名字要么未定义,要么是对于程序员没有意义的内部名(比如在 Java 中,很多情况下文本节点的 nodeName 被报告为 “#text”)。从根本上说,必须假设您得自己来处理错误。直接访问 myNode.nodeName 然后使用该值是危险的,很多情况下这个值为空。因此与通常的编程一样,程序员要谨慎从事。


通用节点类型

现在已经介绍了 DOM 节点的一些特性和属性(以及一些奇特的地方),下面开始讲述您将用到的一些特殊节点类型。多数 Web 应用程序中只用到四种节点类型:

文档节点表示整个 HTML 文档。
元素节点表示 HTML 元素,如 a 或 img。
属性节点表示 HTML 元素的属性,如 href(a 元素)或 src(img 元素)。
文本节点表示 HTML 文档中的文本,如 “Click on the link below for a complete set list”。这是出现在 p、a 或 h2 这些元素中的文字。
处理 HTML 时,95% 的时间是跟这些节点类型打交道。因此本文的其余部分将详细讨论这些节点。(将来讨论 XML 的时候将介绍其他一些节点类型。)


文档节点

基本上所有基于 DOM 的代码中都要用到的第一个节点类型是文档节点。文档节点 实际上并不是 HTML(或 XML)页面中的一个元素而是页面本身。因此在 HTML Web 页面中,文档节点就是整个 DOM 树。在 JavaScript 中,可以使用关键字 document 访问文档节点:

// These first two lines get the DOM tree for the current Web page,
// and then the html element for that DOM tree
var myDocument = document
var htmlElement = myDocument.documentElement




JavaScript 中的 document 关键字返回当前网页的 DOM 树。从这里可以开始处理树中的所有节点。

也可使用 document 对象创建新节点,如下所示:

createElement(elementName) 使用给定的名称创建一个元素。
createTextNode(text) 使用提供的文本创建一个新的文本节点。
createAttribute(attributeName) 用提供的名称创建一个新属性。
这里的关键在于这些方法创建节点,但是并没有将其附加或者插入到特定的文档中。因此,必须使用前面所述的方法如 insertBefore() 或 appendChild() 来完成这一步。因此,可使用下面的代码创建新元素并将其添加到文档中:

var pElement = myDocument.createElement("p")
var text = myDocument.createTextNode("Heres some text in a p element.")
pElement.appendChild(text)
bodyElement.appendChild(pElement)




一旦使用 document 元素获得对 Web 页面 DOM 树的访问,就可以直接使用元素、属性和文本了。


元素节点

虽然会大量使用元素节点,但很多需要对元素执行的操作都是所有节点共有的方法和属性,而不是元素特有的方法和属性。元素只有两组专有的方法:

与属性处理有关的方法:
getAttribute(name) 返回名为 name 的属性值。
removeAttribute(name) 删除名为 name 的属性。
setAttribute(name, value) 创建一个名为 name 的属性并将其值设为 value。
getAttributeNode(name) 返回名为 name 的属性节点(属性节点在 下一节 介绍)。
removeAttributeNode(node) 删除与指定节点匹配的属性节点。
与查找嵌套元素有关的方法:
getElementsByTagName(elementName) 返回具有指定名称的元素节点列表。
这些方法意义都很清楚,但还是来看几个例子吧。

处理属性

处理元素很简单,比如可用 document 对象和上述方法创建一个新的 img 元素:

var imgElement = document.createElement("img")
imgElement.setAttribute("src", "
http://www.headfirstlabs.com/Images/hraj_cover-150.jpg
")
imgElement.setAttribute("width", "130")
imgElement.setAttribute("height", "150")
bodyElement.appendChild(imgElement)




现在看起来应该非常简单了。实际上,只要理解了节点的概念并知道有哪些方法可用,就会发现在 Web 页面和 JavaScript 代码中处理 DOM 非常简单。在上述代码中,JavaScript 创建了一个新的 img 元素,设置了一些属性然后添加到 HTML 页面的 body 元素中。

查找嵌套元素

发现嵌套的元素很容易。比如,下面的代码用于发现和删除 清单 3 所示 HTML 页面中的所有 img 元素:


// Remove all the top-level img elements in the body
if (bodyElement.hasChildNodes()) {
for (i=0 ibodyElement.childNodes.length i++) {
var currentNode = bodyElement.childNodes
if (currentNode.nodeName.toLowerCase() == "img") {
bodyElement.removeChild(currentNode)
}
}
}




也可以使用 getElementsByTagName() 完成类似的功能:



// Remove all the top-level img elements in the body
var imgElements = bodyElement.getElementsByTagName("img")

for (i=0 iimgElements.length i++) {
var imgElement = imgElements.item
bodyElement.removeChild(imgElement)
}




属性节点

DOM 将属性表示成节点,可以通过元素的 attributes 来访问元素的属性,如下所示:



// Remove all the top-level img elements in the body
var imgElements = bodyElement.getElementsByTagName("img")

for (i=0 iimgElements.length i++) {
var imgElement = imgElements.item

// Print out some information about this element
var msg = "Found an img element!"
var atts = imgElement.attributes
for (j=0 jatts.length j++) {
var att = atts.item(j)
msg = msg + "n " + att.nodeName + ": " + att.nodeValue + ""
}
alert(msg)

bodyElement.removeChild(imgElement)
}




属性的奇特之处

对于 DOM 来说属性有一些特殊的地方。一方面,属性实际上并不像其他元素或文本那样是元素的孩子,换句话说,属性并不出现在元素 “之下”。同时,属性显然和元素有一定的关系,元素 “拥有” 属性。DOM 使用节点表示属性,并允许通过元素的专门列表来访问属性。因此属性是 DOM 树的一部分,但通常不出现在树中。有理由说,属性和 DOM 树结构其他部分之间的关系有点模糊。



需要指出的是,attributes 属性实际上是对节点类型而非局限于元素类型来说的。有点古怪,不影响您编写代码,但是仍然有必要知道这一点。

虽然也能使用属性节点,但通常使用元素类的方法处理属性更简单。其中包括:

getAttribute(name) 返回名为 name 的属性值。
removeAttribute(name) 删除名为 name 的属性。
setAttribute(name, value) 创建一个名为 name 的属性并将其值设为 value。
这三个方法不需要直接处理属性节点。但允许使用简单的字符串属性设置和删除属性及其值。


文本节点

需要考虑的最后一种节点是文本节点(至少在处理 HTML DOM 树的时候如此)。基本上通常用于处理文本节点的所有属性都属于节点对象。实际上,一般使用 nodeValue 属性来访问文本节点的文本,如下所示:


var pElements = bodyElement.getElementsByTagName("p")
for (i=0 ipElements.length i++) {
var pElement = pElements.item(i)
var text = pElement.firstChild.nodeValue
alert(text)
}

少数其他几种方法是专门用于文本节点的。这些方法用于增加或分解节点中的数据:

appendData(text) 将提供的文本追加到文本节点的已有内容之后。
insertData(position, text) 允许在文本节点的中间插入数据。在指定的位置插入提供的文本。
replaceData(position, length, text) 从指定位置开始删除指定长度的字符,用提供的文本代替删除的文本。

什么节点类型?

到目前为止看到的多数代码都假设已经知道处理的节点是什么类型,但情况并非总是如此。比方说,如果在 DOM 树中导航并处理一般的节点类型,可能就不知道您遇到了元素还是文本。也许获得了 p 元素的所有孩子,但是不能确定处理的是文本、b 元素还是 img 元素。这种情况下,在进一步的处理之前需要确定是什么类型的节点。

所幸的是很容易就能做到。DOM 节点类型定义了一些常量,比如:

Node.ELEMENT_NODE 是表示元素节点类型的常量。
Node.ATTRIBUTE_NODE 是表示属性节点类型的常量。
Node.TEXT_NODE 是表示文本节点类型的常量。
Node.DOCUMENT_NODE 是表示文档节点类型的常量。
还有其他一些节点类型,但是对于 HTML 除了这四种以外很少用到。我有意没有给出这些常量的值,虽然 DOM 规范中定义了这些值,永远不要直接使用那些值,因为这正是常量的目的!

nodeType 属性

可使用 nodeType 属性比较节点和上述常量 —— 该属性定义在 DOM node 类型上因此可用于所有节点,如下所示:


var someNode = document.documentElement.firstChild
if (someNode.nodeType == Node.ELEMENT_NODE) {
alert("Weve found an element node named " + someNode.nodeName)
} else if (someNode.nodeType == Node.TEXT_NODE) {
alert("Its a text node the text is " + someNode.nodeValue)
} else if (someNode.nodeType == Node.ATTRIBUTE_NODE) {
alert("Its an attribute named " + someNode.nodeName
+ " with a value of " + someNode.nodeValue + "")
}


这个例子非常简单,但说明了一个大问题:得到节点的类型非常 简单。更有挑战性的是知道节点的类型之后确定能做什么,只要掌握了节点、文本、属性和元素类型提供了什么属性和方法,就可以自己进行 DOM 编程了。

好了,快结束了。

实践中的挫折

nodeType 属性似乎是使用节点的一个入场券 —— 允许确定要处理的节点类型然后编写处理该节点的代码。问题在于上述 Node 常量定义不能正确地用于 Internet Explorer。因此如果在代码中使用 Node.ELEMENT_NODE、Node.TEXT_NODE 或其他任何常量,Internet Explorer 都将返回如 图 4 所示的错误。


图 4. Internet Explorer 报告错误



任何时候在 JavaScript 中使用 Node 常量,Internet Explorer 都会报错。因为多数人仍然在使用 Internet Explorer,应该避免在代码中使用 Node.ELEMENT_NODE 或 Node.TEXT_NODE 这样的构造。尽管据说即将发布的新版本 Internet Explorer 7.0 将解决这个问题,但是在 Internet Explorer 6.x 退出舞台之前仍然要很多年。因此应避免使用 Node,要想让您的 DOM 代码(和 Ajax 应用程序)能用于所有主要浏览器,这一点很重要。


结束语

准备成为顶尖的网页设计师吗?

如果您准备了解甚至掌握 DOM,您就会成为最顶尖的 Web 编程人员。多数 Web 程序员知道如何使用 JavaScript 编写图像滚动或者从表单中提取值,有些甚至能够向服务器发送请求和接收响应(阅读本系列的前几篇文章之后您也能做到)。但胆小鬼或者没有经验的人不可能做到即时修改网页结构。



在本系列的上几期文章中您已经学习了很多。现在,您不 应该再坐等下一篇文章期待我介绍各种聪明的 DOM 树用法。现在的家庭作业是看看如何使用 DOM 创造出富有想像力的效果或者漂亮的界面。利用近几期文章中所学的知识开始实验和练习。看看能否建立感觉更与桌面应用程序接近的网站,对象能够响应用户的动作在屏幕上移动。

最好在屏幕上为每个对象画一个边界,这样就能看到 DOM 树中的对象在何处,然后再移动对象。创建节点并将其添加到已有的孩子列表中,删除没有嵌套节点的空节点,改变节点的 CSS 样式,看看孩子节点是否会继承这些修改。可能性是无限的,每当尝试一些新东西时,就学到了一些新的知识。尽情地修改您的网页吧!

在 DOM 三部曲的最后一期文章中,我将 介绍如何把一些非常棒的有趣的 DOM 应用结合到编程中。我将不再是从概念上说教和解释 API,而会提供一些代码。在此之前先发挥您自己的聪明才智,看看能做些什么


参考资料

学习


您可以参阅本文在 developerWorks 全球站点上的 英文原文。


阅读介绍 Ajax 的本 developerWorks 系列文章的前几期:
“Ajax 简介:理解 Ajax 及其工作原理,构建网站的一种有效方法”:第 1 部分示范了各种 Ajax 技术如何协同工作,并介绍了 Ajax 的核心概念,包括 XMLHttpRequest 对象(2005 年 12 月)。
“使用 JavaScript 和 Ajax 发出异步请求”:第 2 部分说明如何以跨浏览器的方式创建 XMLHttpRequest 实例、构造和发送请求、响应服务器(2006 年 1 月)。
“Ajax 中的高级请求和响应”:第 3 部分说明了标准 Web 表单如何与 Ajax 交互,以及如何掌握 HTTP 状态码、就绪状态以及 XMLHttpRequest 对象(2006 年 2 月)。
利用 DOM 进行 Web 响应:第 4 部分介绍 DOM,说明如何将 HTML 转化成对象模型使网页更富响应性和交互性(2006 年 3 月)。


Philip McCarthy 撰写的 面向 Java 开发人员的 Ajax: 构建动态的 Java 应用程序:从 Java 的角度在服务器端考察 Ajax,创建动态 Web 应用程序体验的一种创造性方法(developerWorks,2005 年 9 月)。


Philip McCarthy 撰写的 面向 Java 开发人员的 Ajax: Ajax 的 Java 对象序列化:讨论了 Java 对象序列化的五种方法,分析了如何通过网络发送对象以及与 Ajax 交互(developerWorks,2005 年 10 月)。


James Snell 撰写的 使用 AJAX 调用 SOAP Web 服务,第 1 部分: 构建 Web 服务客户机:这篇高级文章介绍了如何将 Ajax 与现有的基于 SOAP 的 Web 服务结合起来,说明了如何使用 Ajax 设计模式实现基于 Web 浏览器的 SOAP Web 服务客户机(developerWorks,2005 年 10 月)。


Ajax: A New Approach to Web Applications:这篇文章发明了 Ajax 这个名字,所有 Ajax 开发人员都应该阅读它。


万维网联盟的 DOM 主页:这是和 DOM 有关的一切的发源地。


The DOM Level 3 Core Specification:定义了核心文档对象模型,从可用的类型和属性到 DOM 在不同语言中的用法。


ECMAScript language bindings for DOM:如果您是一位 JavaScript 程序员,并希望在代码中使用 DOM,可能会对 Level 3 Document Object Model Core 定义的这个附录感兴趣。


developerWorks Web 体系结构专区:通过这些文章、教程和论坛等提高您的 Web 构建技能。


developerWorks 技术事件和网络广播:关注这些针对技术开发人员的软件会议。

获得产品和技术


Brett McLaughlin 所著的 Head Rush Ajax(OReilly Media, Inc.,2006 年 3 月):深入浅出地将本文中的思想印入您的脑海。


Java and XML, Second Edition(Brett McLaughlin,2001 年 8 月,OReilly Media, Inc.):看看作者关于 XHTML 和 XML 转换的讨论。



javascript
: The Definitive Guide(David Flanagan,2001 年 11 月,OReilly Media, Inc.):深入了解关于使用 JavaScript 和动态 Web 页面的各种建议。下一版将增加关于 Ajax 的两章。


Head First HTML with CSS XHTML(Elizabeth 与 Eric Freeman,2005 年 12 月,OReilly Media, Inc.):进一步了解标准 HTML 和 XHTML,以及如何将 CSS 应用于 HTML。


IBM 试用软件:用这些软件开发您的下一个项目,可直接从 developerWorks 下载。

讨论


developerWorks blogs:加入 developerWorks 社区。
关于作者








Brett McLaughlin 从 Logo 时代就开始使用计算机了。(还记得那个小三角吗?)近年来,他已经成为 Java 和 XML 社区中最受欢迎的作者和程序员之一了。他曾经在 Nextel Communications 实现过复杂的企业系统,在 Lutris Technologies 编写过应用服务器,最近在 OReilly Media, Inc. 继续撰写和编辑这方面的图书。Brett 最新的著作 Head Rush Ajax,为 Ajax 带来了获奖的创新 Head First 方法。他的近作 Java 1.5 Tiger: A Developers Notebook 是关于这一 Java 技术最新版本的第一部专著。经典作品 Java and XML 仍然是在 Java 语言中使用 XML 技术的权威著作之一。

点赞0 收藏
发表回复
发表回复