操纵DOM

日期: 2008-07-08 作者:Brett McLaughlin 来源:TechTarget中国

  上一期中Brett介绍了文档对象模型(DOM),它的元素在幕后定义了Web页面。这一期文章中他将进一步探讨DOM。了解如何创建、删除和修改DOM树的各个部分,了解如何实现网页的即时更新!


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


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


  注意,下面的讨论以上一期文章“利用DOM进行Web响应”为基础,如果没有阅读过那一期,请在继续阅读之前首先阅读上一期文章。


  跨浏览器、跨语言


  文档对象模型是一种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中有的话)全都是节点。因此在讨论这些具体的类型之前必须清楚地把握什么是节点。


  节点是……


  用最简单的话说,节点就是DMO树中的任何事物。之所以用 “事物” 这个模糊的字眼,是因为只能明确到这个程度。比如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”)[0];
    if (headElement != null) {
      alert(“We found the head element, named ” + headElement.nodeName);
      // Print out the title of the page
      var titleElement = headElement.getElementsByTagName(“title”)[0];
      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 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”)[0];
    if (headElement != null) {
      alert(“We found the head element, named ” + headElement.nodeName);
      // Print out the title of the page
      var titleElement = headElement.getElementsByTagName(“title”)[0];
      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…
      // Remove all the top-level <img> elements in the body
      if (bodyElement.hasChildNodes()) {
        for (i=0; i<bodyElement.childNodes.length; i++) {
          var currentNode = bodyElement.childNodes[i];
          if (currentNode.nodeName.toLowerCase() == “img”) {
            bodyElement.removeChild(currentNode);
          }
        }
      }
    }
 
  测试一下!


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


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


  <html>
   <head>
    <title>JavaScript and the DOM</title>
    <script language=”JavaScript”>
     function test() {
      // 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”)[0];
    if (headElement != null) {
      alert(“We found the head element, named ” + headElement.nodeName);
      // Print out the title of the page
      var titleElement = headElement.getElementsByTagName(“title”)[0];
      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…
      // Remove all the top-level <img> elements in the body
      if (bodyElement.hasChildNodes()) {
        for (i=0; i<bodyElement.childNodes.length; i++) {
          var currentNode = bodyElement.childNodes[i];
          if (currentNode.nodeName.toLowerCase() == “img”) {
            bodyElement.removeChild(currentNode);
          }
        }
      }
      }
    }
    </script>
   </head>
   <body>
    <p>JavaScript and DOM are a perfect match.
       You can read more in <i>Head Rush Ajax</i>.</p>
    <img src=”/upload/20087/200878142335639.jpg” />
    <input type=”button” value=”Test me!” onClick=”test();” />
   </body>
  </html>
 
  将该页面加载到浏览器后,可以看到类似图1所示的画面。



  图1. 用按钮运行JavaScript的HTML页面
 
  单击Test me! 将看到图2所示的警告框。



  图2. 使用nodeValue显示元素名的警告框
 
  代码运行完成后,图片将从页面中实时删除,如图3所示。



  图3. 使用JavaScript实时删除图像
 
  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(“Here’s 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”, “/upload/20087/200878142335639.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; i<bodyElement.childNodes.length; i++) {
          var currentNode = bodyElement.childNodes[i];
          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; i<imgElements.length; i++) {
        var imgElement = imgElements.item[i];
        bodyElement.removeChild(imgElement);
      }
 
  属性节点


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


  // Remove all the top-level <img> elements in the body
      var imgElements = bodyElement.getElementsByTagName(“img”);
      for (i=0; i<imgElements.length; i++) {
        var imgElement = imgElements.item[i];
        // Print out some information about this element
        var msg = “Found an img element!”;
        var atts = imgElement.attributes;
        for (j=0; j<atts.length; j++) {
          var att = atts.item(j);
          msg = msg + “n  ” + att.nodeName + “: ’” + att.nodeValue + “’”;
        }
        alert(msg);
        bodyElement.removeChild(imgElement);
      }
 
  需要指出的是,attributes属性实际上是对节点类型而非局限于元素类型来说的。有点古怪,不影响您编写代码,但是仍然有必要知道这一点。


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


  ·getAttribute(name)返回名为name的属性值。
  ·removeAttribute(name)删除名为name的属性。
  ·setAttribute(name, value)创建一个名为name的属性并将其值设为value。


  这三个方法不需要直接处理属性节点。但允许使用简单的字符串属性设置和删除属性及其值。


  文本节点


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


  var pElements = bodyElement.getElementsByTagName(“p”);
  for (i=0; i<pElements.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(“We’ve found an element node named ” + someNode.nodeName);
} else if (someNode.nodeType == Node.TEXT_NODE) {
  alert(“It’s a text node; the text is ” + someNode.nodeValue);
  } else if (someNode.nodeType == Node.ATTRIBUTE_NODE) {
  alert(“It’s 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树用法。现在的家庭作业是看看如何使用DOM创造出富有想像力的效果或者漂亮的界面。利用近几期文章中所学的知识开始实验和练习。看看能否建立感觉更与桌面应用程序接近的网站,对象能够响应用户的动作在屏幕上移动。


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


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

我们一直都在努力坚持原创.......请不要一声不吭,就悄悄拿走。

我原创,你原创,我们的内容世界才会更加精彩!

【所有原创内容版权均属TechTarget,欢迎大家转发分享。但未经授权,严禁任何媒体(平面媒体、网络媒体、自媒体等)以及微信公众号复制、转载、摘编或以其他方式进行使用。】

微信公众号

TechTarget微信公众号二维码

TechTarget

官方微博

TechTarget中国官方微博二维码

TechTarget中国

相关推荐