DIV CSS 佈局教程網

Ajax與DOM操作
編輯:AJAX詳解     
上一篇中 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")[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="/School/UploadFiles_7810/201107/20110720221859245.jpg" />
  <input type="button" value="Test me!" onClick="test();" />
 </body>
</Html>

  將該頁面加載到浏覽器後,可以看到類似 圖 1 所示的畫面。

  圖 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 將報告錯誤,代碼不會按照預期的方式執行。

讓程序員小心謹慎
  如果深入研究 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 樹的訪問,就可以直接使用元素、屬性和文本了。

  元素節點

  雖然會大量使用元素節點,但很多需要對元素執行的操作都是所有節點共有的方法和屬性,而不是元素特有的方法和屬性。元素只有兩組專有的方法:

  1. 與屬性處理有關的方法:

  o getAttribute(name) 返回名為 name 的屬性值。
  o removeAttribute(name) 刪除名為 name 的屬性。
  o setAttribute(name, value) 創建一個名為 name 的屬性並將其值設為 value。
  o getAttributeNode(name) 返回名為 name 的屬性節點(屬性節點在 下一節 介紹)。
  o removeAttributeNode(node) 刪除與指定節點匹配的屬性節點。
  2. 與查找嵌套元素有關的方法:

  o getElementsByTagName(elementName) 返回具有指定名稱的元素節點列表。
  這些方法意義都很清楚,但還是來看幾個例子吧。
 處理屬性
  處理元素很簡單,比如可用 document 對象和上述方法創建一個新的 img 元素:

var imgElement = document.createElement("img");
imgElement.setAttribute("src", "/School/UploadFiles_7810/201107/20110720221859245.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 節點類型定義了一些常量,比如:

  •   1. Node.ELEMENT_NODE 是表示元素節點類型的常量。
  •   2. Node.ATTRIBUTE_NODE 是表示屬性節點類型的常量。
  •   3. Node.TEXT_NODE 是表示文本節點類型的常量。
  •   4. 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,而會提供一些代碼。在此之前先發揮您自己的聰明才智,看看能做些什麼

XML學習教程| jQuery入門知識| AJAX入門| Dreamweaver教程| Fireworks入門知識| SEO技巧| SEO優化集錦|
Copyright © DIV+CSS佈局教程網 All Rights Reserved