国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
第 5 部分 操縱 DOM使用 JavaScript 即時更新 Web 頁面 (2)

API 設計問題

再看一看各種節(jié)點提供的屬性和方法。對于那些熟悉面向對象(OO)編程的人來說,它們說明了 DOM 的一個重要特點:DOM 并非完全面向對象的 API。首先,很多情況下要直接使用對象的屬性而不是調用節(jié)點對象的方法。比方說,沒有 getNodeName() 方法,而要直接使用 nodeName 屬性。因此節(jié)點對象(以及其他 DOM 對象)通過屬性而不是函數(shù)公開了大量數(shù)據(jù)。

其次,如果習慣于使用重載對象和面向對象的 API,特別是 Java 和 C++ 這樣的語言,就會發(fā)現(xiàn) DOM 中的對象和方法命名有點奇怪。DOM 必須能用于 C、Java 和 JavaScript(這只是其中的幾種語言),因此 API 設計作了一些折衷。比如,NamedNodeMap 方法有兩種不同的形式:

  • getNamedItem(String name)
  • getNamedItemNS(Node node)

對于 OO 程序員來說這看起來非常奇怪。兩個方法目的相同,只不過一個使用 String 參數(shù)而另一個使用 Node 參數(shù)。多數(shù) OO API 中對這兩種版本都會使用相同的方法名。運行代碼的虛擬機將根據(jù)傳遞給方法的對象類型決定運行哪個方法。

問題在于 JavaScript 不支持這種稱為方法重載 的技術。換句話說,JavaScript 要求每個方法或函數(shù)使用不同的名稱。因此,如果有了一個名為 getNamedItem() 的接受字符串參數(shù)的方法,就不能再有另一個方法或函數(shù)也命名為 getNamedItem(),即使這個方法的參數(shù)類型不同(或者完全不同的一組參數(shù))。如果這樣做,JavaScript 將報告錯誤,代碼不會按照預期的方式執(zhí)行。

從根本上說,DOM 有意識地避開了方法重載和其他 OO 編程技術。這是為了保證該 API 能夠用于多種語言,包括那些不支持 OO 編程技術的語言。后果不過是要求您多記住一些方法名而已。好處是可以在任何語言中學習 DOM,比如 Java,并清楚同樣的方法名和編碼結構也能用于具有 DOM 實現(xiàn)的其他語言,如 JavaScript。

讓程序員小心謹慎

如果深入研究 API 設計或者僅僅非常關注 API 設計,您可能會問:“為何節(jié)點類型的屬性不能適用于所有節(jié)點?” 這是一個很好的問題,問題的答案與政治及決策關系更密切,而非技術原因。簡單地說,答案就是,“誰知道!但有點令人惱火,不是嗎?”

屬性 nodeName 意味著允許每種類型的節(jié)點都有一個名字,但是很多情況下名字要么未定義,要么是對于程序員沒有意義的內部名(比如在 Java 中,很多情況下文本節(jié)點的 nodeName 被報告為 “#text”)。從根本上說,必須假設您得自己來處理錯誤。直接訪問 myNode.nodeName 然后使用該值是危險的,很多情況下這個值為空。因此與通常的編程一樣,程序員要謹慎從事。

通用節(jié)點類型

現(xiàn)在已經介紹了 DOM 節(jié)點的一些特性和屬性(以及一些奇特的地方),下面開始講述您將用到的一些特殊節(jié)點類型。多數(shù) Web 應用程序中只用到四種節(jié)點類型:

  • 文檔節(jié)點表示整個 HTML 文檔。
  • 元素節(jié)點表示 HTML 元素,如 aimg。
  • 屬性節(jié)點表示 HTML 元素的屬性,如 hrefa 元素)或 srcimg 元素)。
  • 文本節(jié)點表示 HTML 文檔中的文本,如 “Click on the link below for a complete set list”。這是出現(xiàn)在 p、ah2 這些元素中的文字。

處理 HTML 時,95% 的時間是跟這些節(jié)點類型打交道。因此本文的其余部分將詳細討論這些節(jié)點。(將來討論 XML 的時候將介紹其他一些節(jié)點類型。)

文檔節(jié)點

基本上所有基于 DOM 的代碼中都要用到的第一個節(jié)點類型是文檔節(jié)點。文檔節(jié)點 實際上并不是 HTML(或 XML)頁面中的一個元素而是頁面本身。因此在 HTML Web 頁面中,文檔節(jié)點就是整個 DOM 樹。在 JavaScript 中,可以使用關鍵字 document 訪問文檔節(jié)點:

 // 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 樹。從這里可以開始處理樹中的所有節(jié)點。

也可使用 document 對象創(chuàng)建新節(jié)點,如下所示:

  • createElement(elementName) 使用給定的名稱創(chuàng)建一個元素。
  • createTextNode(text) 使用提供的文本創(chuàng)建一個新的文本節(jié)點。
  • createAttribute(attributeName) 用提供的名稱創(chuàng)建一個新屬性。

這里的關鍵在于這些方法創(chuàng)建節(jié)點,但是并沒有將其附加或者插入到特定的文檔中。因此,必須使用前面所述的方法如 insertBefore()appendChild() 來完成這一步。因此,可使用下面的代碼創(chuàng)建新元素并將其添加到文檔中:

 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 樹的訪問,就可以直接使用元素、屬性和文本了。

元素節(jié)點

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

  1. 與屬性處理有關的方法
    • getAttribute(name) 返回名為 name 的屬性值。
    • removeAttribute(name) 刪除名為 name 的屬性。
    • setAttribute(name, value) 創(chuàng)建一個名為 name 的屬性并將其值設為 value。
    • getAttributeNode(name) 返回名為 name 的屬性節(jié)點(屬性節(jié)點在 下一節(jié) 介紹)。
    • removeAttributeNode(node) 刪除與指定節(jié)點匹配的屬性節(jié)點。
  2. 與查找嵌套元素有關的方法
    • getElementsByTagName_r(elementName) 返回具有指定名稱的元素節(jié)點列表。

這些方法意義都很清楚,但還是來看幾個例子吧。

處理屬性

處理元素很簡單,比如可用 document 對象和上述方法創(chuàng)建一個新的 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);  

現(xiàn)在看起來應該非常簡單了。實際上,只要理解了節(jié)點的概念并知道有哪些方法可用,就會發(fā)現(xiàn)在 Web 頁面和 JavaScript 代碼中處理 DOM 非常簡單。在上述代碼中,JavaScript 創(chuàng)建了一個新的 img 元素,設置了一些屬性然后添加到 HTML 頁面的 body 元素中。

查找嵌套元素

發(fā)現(xiàn)嵌套的元素很容易。比如,下面的代碼用于發(fā)現(xiàn)和刪除 清單 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_r() 完成類似的功能:

 // Remove all the top-level <img> elements in the body var imgElements = bodyElement.getElementsByTagName_r("img"); for (i=0; i<imgElements.length; i++) { var imgElement = imgElements.item[i]; bodyElement.removeChild(imgElement); }  

屬性節(jié)點

DOM 將屬性表示成節(jié)點,可以通過元素的 attributes 來訪問元素的屬性,如下所示:

 // Remove all the top-level <img> elements in the body var imgElements = bodyElement.getElementsByTagName_r("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); }  

屬性的奇特之處

對于 DOM 來說屬性有一些特殊的地方。一方面,屬性實際上并不像其他元素或文本那樣是元素的孩子,換句話說,屬性并不出現(xiàn)在元素 “之下”。同時,屬性顯然和元素有一定的關系,元素 “擁有” 屬性。DOM 使用節(jié)點表示屬性,并允許通過元素的專門列表來訪問屬性。因此屬性是 DOM 樹的一部分,但通常不出現(xiàn)在樹中。有理由說,屬性和 DOM 樹結構其他部分之間的關系有點模糊。

需要指出的是,attributes 屬性實際上是對節(jié)點類型而非局限于元素類型來說的。有點古怪,不影響您編寫代碼,但是仍然有必要知道這一點。

雖然也能使用屬性節(jié)點,但通常使用元素類的方法處理屬性更簡單。其中包括:

  • getAttribute(name) 返回名為 name 的屬性值。
  • removeAttribute(name) 刪除名為 name 的屬性。
  • setAttribute(name, value) 創(chuàng)建一個名為 name 的屬性并將其值設為 value

這三個方法不需要直接處理屬性節(jié)點。但允許使用簡單的字符串屬性設置和刪除屬性及其值。

文本節(jié)點

需要考慮的最后一種節(jié)點是文本節(jié)點(至少在處理 HTML DOM 樹的時候如此)。基本上通常用于處理文本節(jié)點的所有屬性都屬于節(jié)點對象。實際上,一般使用 nodeValue 屬性來訪問文本節(jié)點的文本,如下所示:

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

少數(shù)其他幾種方法是專門用于文本節(jié)點的。這些方法用于增加或分解節(jié)點中的數(shù)據(jù):

  • appendData(text) 將提供的文本追加到文本節(jié)點的已有內容之后。
  • insertData(position, text) 允許在文本節(jié)點的中間插入數(shù)據(jù)。在指定的位置插入提供的文本。
  • replaceData(position, length, text) 從指定位置開始刪除指定長度的字符,用提供的文本代替刪除的文本。

    什么節(jié)點類型?

    到目前為止看到的多數(shù)代碼都假設已經知道處理的節(jié)點是什么類型,但情況并非總是如此。比方說,如果在 DOM 樹中導航并處理一般的節(jié)點類型,可能就不知道您遇到了元素還是文本。也許獲得了 p 元素的所有孩子,但是不能確定處理的是文本、b 元素還是 img 元素。這種情況下,在進一步的處理之前需要確定是什么類型的節(jié)點。

    所幸的是很容易就能做到。DOM 節(jié)點類型定義了一些常量,比如:

    1. Node.ELEMENT_NODE 是表示元素節(jié)點類型的常量。
    2. Node.ATTRIBUTE_NODE 是表示屬性節(jié)點類型的常量。
    3. Node.TEXT_NODE 是表示文本節(jié)點類型的常量。
    4. Node.DOCUMENT_NODE 是表示文檔節(jié)點類型的常量。

    還有其他一些節(jié)點類型,但是對于 HTML 除了這四種以外很少用到。我有意沒有給出這些常量的值,雖然 DOM 規(guī)范中定義了這些值,永遠不要直接使用那些值,因為這正是常量的目的!

    nodeType 屬性

    可使用 nodeType 屬性比較節(jié)點和上述常量 —— 該屬性定義在 DOM node 類型上因此可用于所有節(jié)點,如下所示:

     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 + "'"); }  

    這個例子非常簡單,但說明了一個大問題:得到節(jié)點的類型非常 簡單。更有挑戰(zhàn)性的是知道節(jié)點的類型之后確定能做什么,只要掌握了節(jié)點、文本、屬性和元素類型提供了什么屬性和方法,就可以自己進行 DOM 編程了。

    好了,快結束了。

    實踐中的挫折

    nodeType 屬性似乎是使用節(jié)點的一個入場券 —— 允許確定要處理的節(jié)點類型然后編寫處理該節(jié)點的代碼。問題在于上述 Node 常量定義不能正確地用于 Internet Explorer。因此如果在代碼中使用 Node.ELEMENT_NODE、Node.TEXT_NODE 或其他任何常量,Internet Explorer 都將返回如 圖 4 所示的錯誤。


    圖 4. Internet Explorer 報告錯誤

    任何時候在 JavaScript 中使用 Node 常量,Internet Explorer 都會報錯。因為多數(shù)人仍然在使用 Internet Explorer,應該避免在代碼中使用 Node.ELEMENT_NODENode.TEXT_NODE 這樣的構造。盡管據(jù)說即將發(fā)布的新版本 Internet Explorer 7.0 將解決這個問題,但是在 Internet Explorer 6.x 退出舞臺之前仍然要很多年。因此應避免使用 Node,要想讓您的 DOM 代碼(和 Ajax 應用程序)能用于所有主要瀏覽器,這一點很重要。

    結束語

    準備成為頂尖的網頁設計師嗎?

    如果您準備了解甚至掌握 DOM,您就會成為最頂尖的 Web 編程人員。多數(shù) Web 程序員知道如何使用 JavaScript 編寫圖像滾動或者從表單中提取值,有些甚至能夠向服務器發(fā)送請求和接收響應(閱讀本系列的前幾篇文章之后您也能做到)。但膽小鬼或者沒有經驗的人不可能做到即時修改網頁結構。

    在本系列的上幾期文章中您已經學習了很多?,F(xiàn)在,您 應該再坐等下一篇文章期待我介紹各種聰明的 DOM 樹用法?,F(xiàn)在的家庭作業(yè)是看看如何使用 DOM 創(chuàng)造出富有想像力的效果或者漂亮的界面。利用近幾期文章中所學的知識開始實驗和練習??纯茨芊窠⒏杏X更與桌面應用程序接近的網站,對象能夠響應用戶的動作在屏幕上移動。

    最好在屏幕上為每個對象畫一個邊界,這樣就能看到 DOM 樹中的對象在何處,然后再移動對象。創(chuàng)建節(jié)點并將其添加到已有的孩子列表中,刪除沒有嵌套節(jié)點的空節(jié)點,改變節(jié)點的 CSS 樣式,看看孩子節(jié)點是否會繼承這些修改??赡苄允菬o限的,每當嘗試一些新東西時,就學到了一些新的知識。盡情地修改您的網頁吧!

    在 DOM 三部曲的最后一期文章中,我 介紹如何把一些非常棒的有趣的 DOM 應用結合到編程中。我將不再是從概念上說教和解釋 API,而會提供一些代碼。在此之前先發(fā)揮您自己的聰明才智,看看能做些什么

 
本站僅提供存儲服務,所有內容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權內容,請點擊舉報
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
掌握 Ajax,第 5 部分: 操縱 DOM
javascript快速入門15
JavaScript之-文檔對象模型(DOM)
XML DOM介紹
JavaScript HTML DOM 元素(節(jié)點)
JS操作DOM元素屬性和方法(轉)
更多類似文章 >>
生活服務
分享 收藏 導長圖 關注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服