| 導購 | 订阅 | 在线投稿
分享
 
 
 

[四天學會ajax] 學習Ajax教程第四天,利用 DOM 進行 Web 響應

2008-10-02 07:47:51  編輯來源:互聯網  简体版  手機版  評論  字體: ||
 
  在 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 時有了前所未有的靈活性。

  關于標記的其他想法

  純文本編輯:是對是錯?

  純文本是存儲標記的理想選擇,但是不適合編輯 標記。大行其道的是使用 IDE,比如 Macromedia DreamWeaver 或更強勢點的 Microsoft® FrontPage®,來操作 Web 頁面標記。這些環境通常提供快捷方式和幫助來創建 Web 頁面,尤其是在使用 CSS 和 JavaScript 時,二者都來自實際頁面標記以外的文件。許多人仍偏愛好用古老的記事本或 vi(我承認我也是其中一員),這並不要緊。不管怎樣,最終結果都是充滿標記的文本文件。

  網絡上的文本:好東西

  已經說過,文本是文檔的最好媒體,比如 HTML 或 CSS,在網絡上被千百次地傳輸。當我說浏覽器表示文本很難時,是特指將文本轉換爲用戶查看的可視圖形頁面。這與浏覽器實際上如何從 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>

   <title>Trees, trees, everywhere</title>

  </head>

  <body>

   <h1>Trees, trees, everywhere</h1>

   <p>Welcome to a <em>really</em> boring page.</p>

   <div>

   Come again soon.

   <img src="come-again.gif" />

   </div>

  </body>

  </html>

  浏覽器接受該頁面並將之轉換爲樹形結構,如圖 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>

   <title>This is a little tricky</title>

  </head>

  <body>

   <h1>Pay <u>close</u> attention, OK?</h1>

   <div>

   <p>This p really isn't <em>necessary</em>, but it makes the

   <span id="bold-text">structure <i>and</i> the organization</span>

   of the page easier to keep up with.</p>

   </div>

  </body>

  </html>

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

  <html>

  <head>

   <title>Trickier nesting, still</title>

  </head>

  <body>

   <div id="main-body">

   <div id="contents">

   <table>

   <tr><th>Steps</th><th>Process</th></tr>

   <tr><td>1</td><td>Figure out the <em>root element</em>.</td></tr>

   <tr><td>2</td><td>Deal with the <span id="code">head</span> first,

   as it's usually easy.</td></tr>

   <tr><td>3</td><td>Work through the <span id="code">body</span>.

   Just <em>take your time</em>.</td></tr>

   </table>

   </div>

   <div id="closing">

   This link is <em>not</em> active, but if it were, the answers

   to this <a href="answers.html"><img src="exercise.gif" /></a> would

   be there. But <em>do 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> 匹配,等等。

  ·最裏面的開始標記與最裏面的結束標記相匹配,然後次裏面的開始標記與次裏面的結束標記相匹配,依此類推。所以 <b><i>bold 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 定義了對象的類型和屬性,從而允許浏覽器表示標記。(本系列下一篇文章將專門講述在 JavaScript 和 Ajax 代碼中使用 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 的內容要遠遠多于我今天介紹的這些!

  本系列的下一篇文章將擴展這些觀點,並深入探討如何在 JavaScript 中使用 DOM 來更新 Web 頁面、快速更改 HTML 並爲您的用戶創建更交互的體驗。在後面專門講述在 Ajax 請求中使用 XML 的文章中,我將再次返回來討論 DOM。所以要熟悉 DOM,它是 Ajax 應用程序的一個主要部分。

  此時,深入了解 DOM 將十分簡單,比如詳細設計如何在 DOM 樹中移動、獲得元素和文本的值、遍曆節點列表,等等,但這可能會讓您有這種印象,即 DOM 是關于代碼的,而事實上並非如此。

  在閱讀下一篇文章之前,試著思考一下樹結構並用一些您自己的 HTML 實踐一下,以查看 Web 浏覽器是如何將 HTML 轉換爲標記的樹視圖的。此外,思考一下 DOM 樹的組織,並用本文介紹的特殊情況實踐一下:屬性、有元素混合在其中的文本、沒有 文本內容的元素(比如 img 元素)。

  如果紮實掌握了這些概念,然後學習了 JavaScript 和 DOM 的語法(下一篇文章),則會使得響應更爲容易。

  而且不要忘了,這裏有清單 2 和 3 的答案,其中還包含了示例代碼!
 
在 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 時有了前所未有的靈活性。 關于標記的其他想法 純文本編輯:是對是錯? 純文本是存儲標記的理想選擇,但是不適合編輯 標記。大行其道的是使用 IDE,比如 Macromedia DreamWeaver 或更強勢點的 Microsoft® FrontPage®,來操作 Web 頁面標記。這些環境通常提供快捷方式和幫助來創建 Web 頁面,尤其是在使用 CSS 和 JavaScript 時,二者都來自實際頁面標記以外的文件。許多人仍偏愛好用古老的記事本或 vi(我承認我也是其中一員),這並不要緊。不管怎樣,最終結果都是充滿標記的文本文件。 網絡上的文本:好東西 已經說過,文本是文檔的最好媒體,比如 HTML 或 CSS,在網絡上被千百次地傳輸。當我說浏覽器表示文本很難時,是特指將文本轉換爲用戶查看的可視圖形頁面。這與浏覽器實際上如何從 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> <title>Trees, trees, everywhere</title> </head> <body> <h1>Trees, trees, everywhere</h1> <p>Welcome to a <em>really</em> boring page.</p> <div> Come again soon. <img src="come-again.gif" /> </div> </body> </html> 浏覽器接受該頁面並將之轉換爲樹形結構,如圖 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> <title>This is a little tricky</title> </head> <body> <h1>Pay <u>close</u> attention, OK?</h1> <div> <p>This p really isn't <em>necessary</em>, but it makes the <span id="bold-text">structure <i>and</i> the organization</span> of the page easier to keep up with.</p> </div> </body> </html> 清單 3. 更巧妙的元素嵌套 <html> <head> <title>Trickier nesting, still</title> </head> <body> <div id="main-body"> <div id="contents"> <table> <tr><th>Steps</th><th>Process</th></tr> <tr><td>1</td><td>Figure out the <em>root element</em>.</td></tr> <tr><td>2</td><td>Deal with the <span id="code">head</span> first, as it's usually easy.</td></tr> <tr><td>3</td><td>Work through the <span id="code">body</span>. Just <em>take your time</em>.</td></tr> </table> </div> <div id="closing"> This link is <em>not</em> active, but if it were, the answers to this <a href="answers.html"><img src="exercise.gif" /></a> would be there. But <em>do 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> 匹配,等等。 ·最裏面的開始標記與最裏面的結束標記相匹配,然後次裏面的開始標記與次裏面的結束標記相匹配,依此類推。所以 <b><i>bold 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 定義了對象的類型和屬性,從而允許浏覽器表示標記。(本系列下一篇文章將專門講述在 JavaScript 和 Ajax 代碼中使用 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 的內容要遠遠多于我今天介紹的這些! 本系列的下一篇文章將擴展這些觀點,並深入探討如何在 JavaScript 中使用 DOM 來更新 Web 頁面、快速更改 HTML 並爲您的用戶創建更交互的體驗。在後面專門講述在 Ajax 請求中使用 XML 的文章中,我將再次返回來討論 DOM。所以要熟悉 DOM,它是 Ajax 應用程序的一個主要部分。 此時,深入了解 DOM 將十分簡單,比如詳細設計如何在 DOM 樹中移動、獲得元素和文本的值、遍曆節點列表,等等,但這可能會讓您有這種印象,即 DOM 是關于代碼的,而事實上並非如此。 在閱讀下一篇文章之前,試著思考一下樹結構並用一些您自己的 HTML 實踐一下,以查看 Web 浏覽器是如何將 HTML 轉換爲標記的樹視圖的。此外,思考一下 DOM 樹的組織,並用本文介紹的特殊情況實踐一下:屬性、有元素混合在其中的文本、沒有 文本內容的元素(比如 img 元素)。 如果紮實掌握了這些概念,然後學習了 JavaScript 和 DOM 的語法(下一篇文章),則會使得響應更爲容易。 而且不要忘了,這裏有清單 2 和 3 的答案,其中還包含了示例代碼!
󰈣󰈤
 
 
 
>>返回首頁<<
 
 
 
 
 熱帖排行
 
王朝網路微信公眾號
微信掃碼關註本站公眾號 wangchaonetcn
 
  免責聲明:本文僅代表作者個人觀點,與王朝網絡無關。王朝網絡登載此文出於傳遞更多信息之目的,並不意味著贊同其觀點或證實其描述,其原創性以及文中陳述文字和內容未經本站證實,對本文以及其中全部或者部分內容、文字的真實性、完整性、及時性本站不作任何保證或承諾,請讀者僅作參考,並請自行核實相關內容。
 
© 2005- 王朝網路 版權所有