Javascript_DOM編程藝術(shù)中文部分翻譯版_第1頁
Javascript_DOM編程藝術(shù)中文部分翻譯版_第2頁
Javascript_DOM編程藝術(shù)中文部分翻譯版_第3頁
Javascript_DOM編程藝術(shù)中文部分翻譯版_第4頁
Javascript_DOM編程藝術(shù)中文部分翻譯版_第5頁
已閱讀5頁,還剩15頁未讀 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

1、JavaScript DOM 編程藝術(shù)第3章 DOM本章內(nèi)容   節(jié)點的概念  四個非常實用的DOM方法:getElementById、getElementsByTagName、getAttribute和setAttribute終于要與DOM面對面了。能夠向大家介紹DOM是筆者的榮幸,我非常樂于帶領(lǐng)大家通過DOM的眼睛去看世界。3.1文檔:DOM中的“D”DOM是“Document Object Model”(文檔對象模型)的首字母縮寫。如果沒有document(文檔),DOM也就無從談起。當創(chuàng)建了一個網(wǎng)頁并把它加載到Web瀏覽器中時,DOM就在幕后悄然

2、而生。它將根據(jù)你編寫的網(wǎng)頁文檔創(chuàng)建一個文檔對象。在人類語言中,“對象”這個詞的含義往往不那么明確和具體,它幾乎可以用來稱呼任何一種客觀存在的事物。但在程序設計語言中,“對象”這個詞的含義非常明確和具體。3.2對象:DOM中的“O”在上一章的末尾,我們向大家展示了幾個JavaScript對象的例子。你們應該還記得,“對象”是一種獨立的數(shù)據(jù)集合。與某個特定對象相關(guān)聯(lián)的變量被稱為這個對象的屬性;可以通過某個特定對象去調(diào)用的函數(shù)被稱為這個對象的方法。JavaScript語言里的對象可以分為三種類型:  用戶定義對象(user-defined object):由程序員自行創(chuàng)建的對象。

3、本書不討論這種對象。  內(nèi)建對象(native object):內(nèi)建在JavaScript語言里的對象,如Array、Math和Date等。  宿主對象(host object):由瀏覽器提供的對象。在JavaScript語言的發(fā)展初期,程序員在編寫JavaScript腳本時經(jīng)常需要用到一些非常重要的宿主對象,它們當中最基礎(chǔ)的是window對象。window對象對應著瀏覽器窗口本身,這個對象的屬性和方法通常被統(tǒng)稱為BOM(瀏覽器對象模型)但我覺得稱之為Window Object Model(窗口對象模型)更為貼切。BOM向程序員提供了window.ope

4、n和window.blur等方法,你們在上網(wǎng)沖浪時看到的各種彈出窗口和下拉菜單其數(shù)量之多已經(jīng)到了泛濫成災的地步幾乎都是由這些方法負責創(chuàng)建和處理的。難怪JavaScript會有一個不好的名聲!值得慶幸的是,在這本書里我們不需要與BOM打太多的交道。我們將把注意力集中在瀏覽器窗口的內(nèi)部而不是瀏覽器窗口本身。我們將著重探討如何對網(wǎng)頁的內(nèi)容進行處理,而用來實現(xiàn)這一目標的載體就是document對象。在本書的后續(xù)內(nèi)容里,我們將盡可能地只討論document對象的屬性和方法?,F(xiàn)在,我們已經(jīng)對DOM中的字母“D”(document,文檔)和字母“O”(object,對象)做了解釋,那么字母“M”又代表著什么

5、呢?3.3模型:DOM中的“M”DOM中的“M”代表著“Model”(模型),但說它代表著“Map”(地圖)也未嘗不可。模型也好,地圖也罷,它們的含義都是某種事物的表現(xiàn)形式。就像一個模型火車代表著一列真正的火車、一張城市街道圖代表著一個實際存在的城市那樣,DOM代表著被加載到瀏覽器窗口里的當前網(wǎng)頁:瀏覽器向我們提供了當前網(wǎng)頁的地圖(或者說模型),而我們可以通過JavaScript去讀取這張地圖。既然是地圖,就必須有諸如方向、等高線和比例尺之類的記號。要想看懂和使用地圖,就必須知道這些記號的含義和用途這個道理同樣適用于DOM。要想從DOM獲得信息,我們必須先把各種用來表示和描述一份文檔的記號弄明

6、白。DOM把一份文檔表示為一棵樹(這里所說的“樹”是數(shù)學意義上的概念),這是我們理解和運用這一模型的關(guān)鍵。更具體地說,DOM把文檔表示為一棵家譜樹。家譜樹本身又是一種模型。家譜樹的典型用法是表示一個人類家族的譜系并使用parent(父)、child(子)、sibling(兄弟)等記號來表明家族成員之間的關(guān)系。家譜樹可以把一些相當復雜的關(guān)系簡明地表示出來:一位特定的家族成員既是某些成員的父輩,又是另一位成員的子輩,同時還是另一位成員的兄弟。類似于人類家族譜系的情況,家譜樹模型也非常適合用來表示一份用(X)HTML語言編寫出來的文檔。請看下面這份非?;镜木W(wǎng)頁,它的內(nèi)容是一份購物清單。這份文檔可以

7、用圖3-1中的模型來表示。我們來分析一下這個網(wǎng)頁的結(jié)構(gòu)。這種分析不僅可以讓我們了解它是由哪些元素構(gòu)成的,還可以讓我們了解為什么圖3-1中的模型可以如此完美地把它表示出來。在對Doctype做出聲明后,這份文檔首先打開了一個<html>標簽,而這個網(wǎng)頁里的所有其他元素都包含在這個元素里。因為所有其他的元素都包含在其內(nèi)部,所以這個<html>標簽既沒有父輩,也沒有兄弟。如果這是一棵真正的樹的話,這個<html>標簽顯然就是樹根。圖3-1  把網(wǎng)頁中的元素表示為一棵家譜樹這正是圖3-1中的家譜樹以html為根元素的原因。毫無疑問,html元素完全可以代表

8、整個文檔。如果在這份文檔里更深入一層,我們將發(fā)現(xiàn)<head>和<body>兩個分枝。它們存在于同一層次且互不包含,所以它們是兄弟關(guān)系。它們有著共同的父元素<html>,但又各有各的子元素,所以它們本身又是其他一些元素的父元素。<head>元素有兩個子元素:<meta>和<title>(這兩個元素是兄弟關(guān)系)。<body>元素有三個子元素:<h1>、<p>和<ul>(這三個元素是兄弟關(guān)系)。如果繼續(xù)深入下去,我們將發(fā)現(xiàn)<ul>也是一個父元素。它有三個子元素,它們都是

9、<li>元素。利用這種簡單的家譜關(guān)系記號,我們可以把各元素之間的關(guān)系簡明清晰地表達出來。例如,<h1>和<ul>之間是什么關(guān)系?答案是它們是兄弟關(guān)系。那么<body>和<ul>之間又是什么關(guān)系?<body>是<ul>的父元素,<ul>是<body>的一個子元素。如果把各種文檔元素想像成一棵家譜樹上的各個節(jié)點的話,我們就可以用同樣的記號來描述DOM。不過,與使用“家譜樹”這個術(shù)語相比,把一份文檔稱為一棵“節(jié)點樹”更準確。3.3.1節(jié)點節(jié)點(node)這個名詞來自網(wǎng)絡理論,它代表著網(wǎng)絡中的一

10、個連接點。網(wǎng)絡是由節(jié)點構(gòu)成的集合。在現(xiàn)實世界里,一切事物都由原子構(gòu)成。原子是現(xiàn)實世界的節(jié)點。但原子本身還可以進一步分解為更細小的亞原子微粒。這些亞原子微粒同樣是節(jié)點。DOM也是同樣的情況。文檔也是由節(jié)點構(gòu)成的集合,只不過此時的節(jié)點是文檔樹上的樹枝和樹葉而已。在DOM里存在著許多不同類型的節(jié)點。就像原子包含著亞原子微粒那樣,有些DOM節(jié)點類型還包含著其他類型的節(jié)點。1. 元素節(jié)點DOM的原子是元素節(jié)點(element node)。在描述剛才那份“購物清單”文檔時,我們使用了諸如<body>、<p>和<ul>之類的元素。如果把Web上的文檔比作一座大廈,元素就是

11、建造這座大廈的磚塊,這些元素在文檔中的布局形成了文檔的結(jié)構(gòu)。各種標簽提供了元素的名字。文本段落元素的名字是“p”,無序清單元素的名字是“ul”,列表項元素的名字是“l(fā)i”。元素可以包含其他的元素。在我們的“購物清單”文檔里,所有的列表項元素都包含在一個無序清單元素的內(nèi)部。事實上,沒有被包含在其他元素里的唯一元素是<html>元素。它是我們的節(jié)點樹的根元素。2文本節(jié)點元素只是不同節(jié)點類型中的一種。如果一份文檔完全由一些空白元素構(gòu)成,它將有一個結(jié)構(gòu),但這份文檔本身將不會包含什么內(nèi)容。在網(wǎng)上,內(nèi)容決定著一切,沒有內(nèi)容的文檔是沒有任何價值的,而絕大多數(shù)內(nèi)容都是由文本提供的。在“購物清單”例

12、子里,<p>元素包含著文本“Dont forget to buy this stuff.”。它是一個文本節(jié)點(text node)。在XHTML文檔里,文本節(jié)點總是被包含在元素節(jié)點的內(nèi)部。但并非所有的元素節(jié)點都包含有文本節(jié)點。在“購物清單”文檔里,<ul>元素沒有直接包含任何文本節(jié)點它包含著其他的元素節(jié)點(一些<li>元素),后者包含著文本節(jié)點。3屬性節(jié)點還存在著其他一些節(jié)點類型。例如,注釋就是另外一種節(jié)點類型。但我們這里還想向大家再多介紹一種節(jié)點類型。元素都或多或少地有一些屬性,屬性的作用是對元素做出更具體的描述。例如,幾乎所有的元素都有一個title屬性

13、,而我們可以利用這個屬性對包含在元素里的東西做出準確的描述:在DOM中,title="a gentle reminder"是一個屬性節(jié)點(attribute node),如圖3-2所示。因為屬性總是被放在起始標簽里,所以屬性節(jié)點總是被包含在元素節(jié)點當中。并非所有的元素都包含著屬性,但所有的屬性都會被包含在元素里。圖3-2  一個元素節(jié)點,它包含著一個屬性節(jié)點和一個文本節(jié)點在前面的“購物清單”示例文檔里,我們可以清楚地看到那個無序清單元素(<ul>)有個id屬性。如果曾經(jīng)使用過CSS,你們對id和class之類的屬性應該不會感到陌生。不過,為了照顧那些對

14、CSS還不太熟悉的讀者,我們下面將簡要地重溫幾個最基本的CSS概念。4CSS:層疊樣式表DOM并不是人們與網(wǎng)頁的結(jié)構(gòu)打交道的唯一手段。我們還可以通過CSS(層疊樣式表)告訴瀏覽器應該如何顯示一份文檔的內(nèi)容。類似于JavaScript腳本,對樣式的聲明既可以嵌在文檔的<head>部分(這需要用到<style>標簽),也可以放在另外一個樣式表文件里。利用CSS對某個元素的樣式做出聲明的語法與JavaScript函數(shù)的定義語法很相似:在樣式聲明里,我們可以對瀏覽器在顯示各有關(guān)元素時使用的顏色、字體和字號做出定義,如下所示:繼承(inheritance)是CSS技術(shù)中的一項強大

15、功能。類似于DOM,CSS也把文檔的內(nèi)容視為一棵節(jié)點樹。節(jié)點樹上的各個元素將繼承其父元素的樣式屬性。例如,如果我們?yōu)閎ody元素定義了一些顏色或字體,包含在body元素里的所有元素都將自動獲得也就是繼承,那些樣式:這些顏色將不僅作用于那些被直接包含在<body>標簽里的內(nèi)容,還將作用于那些嵌套在body元素內(nèi)部的所有元素。這里是把剛才定義的樣式應用在“購物清單”示例文檔上而得到的網(wǎng)頁顯示效果。在某些場合,當把樣式應用于一份文檔時,我們其實只想讓那些樣式只作用于某個特定的元素。例如,我們只想讓某一段文本變成某種特殊的顏色和字體,但不想讓其他段落受到影響。為了獲得如此精細的控制,我們將

16、需要在文檔里插入一些能夠把這段文本與其他段落區(qū)別開來的特殊標志。為了把某一個或某幾個元素與其他元素區(qū)別開來,我們需要使用class屬性或id屬性之一。l   class屬性所有的元素都有class屬性,不同的元素可以有同樣的class屬性值。如下所示:在樣式表里,我們可以像下面這樣為class屬性值相同的所有元素定義一種共享的樣式:我們還可以像下面這樣利用class屬性為一種特定類型的元素定義一種獨享的樣式:l   id屬性id屬性的用途是給網(wǎng)頁里的某個元素加上一個獨一無二的標識符,如下所示:在樣式表里,我們可以像下面這樣為有著特定id屬性值的元素定義一

17、種獨享的樣式:每個元素只能有一個id屬性值,不同的元素必須有不同的id屬性值。不過,我們可以在樣式表里像下面這樣,利用id屬性為包含在某給定元素里的其他元素定義樣式,而如此定義出來的樣式將只作用于包含在這個給定元素里的有關(guān)元素:這里是把剛才利用id屬性定義的樣式應用在“購物清單”示例文檔上而得到的網(wǎng)頁顯示效果。id屬性就像是一個掛鉤,它一頭連著文檔里的某個元素,另一頭連著CSS樣式表里的某個樣式。DOM也可以使用這種掛鉤,事實上,有不少DOM操作必須借助于這種掛鉤才能完成。3.3.2getElementById()方法DOM提供了一個名為getElementById()的方法,這個方法將返回一

18、個與那個有著給定id屬性值的元素節(jié)點相對應的對象。請注意,JavaScript語言區(qū)分字母的大小寫情況,所以大家在寫出“getElementById”時千萬不要把大小寫弄錯了。如果把它錯寫成“GetElementById”或“getElementbyid”,你將無法得到你真正想要的東西。這個方法是與document對象相關(guān)聯(lián)的函數(shù)。在腳本代碼里,函數(shù)名的后面必須跟有一組圓括號,這組圓括號包含著函數(shù)的參數(shù)。getElementById()方法只有一個參數(shù):你想獲得的那個元素的id屬性值,這個id值必須放在單引號或雙引號里。下面是一個例子:這個調(diào)用將返回一個對象,這個對象對應著document對象

19、里的一個獨一無二的元素,那個元素的HTML id屬性值是purchases。再說一遍,getElementById()方法將返回一個對象。你們可以用typeof操作符來驗證這一點。typeof操作符可以告訴我們它的操作數(shù)是不是一個字符串、數(shù)值、函數(shù)、布爾值或?qū)ο?。下面是把一些JavaScript語句插入到前面給出的“購物清單”文檔之后得到的一份代碼清單,新增的代碼(黑體字部分)出現(xiàn)在</body>結(jié)束標簽之前。順便說一句,我本人并不贊成把JavaScript代碼直接嵌入一份文檔的做法,但它不失為一種簡便快捷的測試手段:把上面這些代碼保存為一個XHTML文件。當在你們的Web瀏覽器里

20、加載這個XHTML文件時,屏幕上將彈出一個如下所示的alter對話框,它向你們報告document.getElementById ("purchases")的類型它是一個對象。不僅如此,如果用上述辦法去檢查其他元素節(jié)點的類型,你們也會看到類似的alert對話框。事實上,文檔中的每一個元素都對應著一個對象。利用DOM提供的方法,我們可以把與這些元素相對應的任何一個對象篩選出來。一般來說,我們用不著為文檔里的每一個元素都分別定義一個獨一無二的id值;那也太小題大做了。要知道,即使某個元素沒有獨一無二的id值,我們也可以利用DOM提供的另一個方法把與之對應的對象準確無誤地篩選出來

21、。3.3.3getElementsByTagName()方法getElementsByTagName()方法將返回一個對象數(shù)組,每個對象分別對應著文檔里有著給定標簽的一個元素。類似于getElementById(),這個方法也是只有一個參數(shù)的函數(shù),它的參數(shù)是(X)HTML標簽的名字:它與getElementById()方法有許多相似之處,但有一點要特別提醒大家注意:getElements- ByTagName()方法返回的是一個數(shù)組;你們在編寫腳本時千萬注意不要把這兩個方法弄混了。下面是一個例子:這個調(diào)用將返回一個對象數(shù)組,每個對象分別對應著document對象中的一個列表項(li)元素。與任

22、何其他的數(shù)組一樣,我們可以利用length屬性查出這個數(shù)組里的元素個數(shù)。首先,在上一小節(jié)給出的XHTML示例文檔里把<script>標簽中的alter語句替換為下面這條語句:然后,用瀏覽器里重新加載那個XHTML文件,你們就會看到這份示例文檔里的列表項元素的個數(shù):3。這個數(shù)組里的每個元素都是一個對象??梢酝ㄟ^利用一個循環(huán)語句和typeof操作符去遍歷這個數(shù)組的辦法來驗證這一點。例如,你們可以試試下面這個for循環(huán):請注意,即使在整個文檔里只有一個元素有著給定的標簽名,getElementsByTagName()方法也將返回一個數(shù)組。此時,那個數(shù)組的長度是1。你們或許早就覺得用鍵盤反

23、復敲入document.getElementsByTagName("li")是件很麻煩的事情,而這些長長的字符串會讓代碼變得越來越難以閱讀。有個簡單的辦法可以減少不必要的打字量并改善代碼的可讀性:只要把document.getElementsByTagName("li")賦值給一個變量即可。請在上一小節(jié)給出的XHTML示例文檔里把<script>標簽中的alter語句替換為下面這些語句:現(xiàn)在,當用瀏覽器里重新加載那個XHTML文件時,你們將看到三個alert對話框,顯示在這三個alert對話框里的消息都是“object”。 getElemen

24、tsByTagName()方法允許我們把一個通配符當為它的參數(shù),而這意味著文檔里的每個元素都將在這個函數(shù)所返回的數(shù)組里占有一席之地。通配符(星號字符“*”)必須放在引號里,這是為了讓通配符與乘法操作符有所區(qū)別。如果你想知道某份文檔里總共有多少個元素節(jié)點,像下面這樣以通配符為參數(shù)去調(diào)用getElementsByTagName()方法是最簡便的辦法:我們還可以把getElementById()和getElementsByTagName()方法結(jié)合起來運用。例如,我們剛才給出的幾個例子都是通過document對象調(diào)用getElementsByTagName()方法的,如果只想知道其id屬性值是pur

25、chase的元素包含著多少個列表項(li)的話,你就必須通過一個更具體的對象去調(diào)用這個方法,如下所示:在這兩條語句執(zhí)行完畢后,items數(shù)組將只包含其id屬性值是purchase的無序清單里的元素。具體到我們這個例子,items數(shù)組的長度剛好與這份文檔里的列表項元素的總數(shù)相等:如果還需要更多的證據(jù),下面這些語句將證明items數(shù)組里的每個值確實是一個對象:3.4趁熱打鐵在看過那么多顯示著單詞“object”的alert對話框后,你們很可能不愿意再看到它。如果真是如此,我的目的也就達到了我想通過這些alert對話框強調(diào)這樣一個事實:文檔中的每個元素節(jié)點都是一個對象。我現(xiàn)在要告訴大家的是,這些對象

26、中的每個都為我們準備了一系列非常有用的方法,而這一切當然都要歸功于DOM。利用這些已經(jīng)預先定義好的方法,我們不僅可以檢索出關(guān)于文檔里的任何一個對象的信息,甚至還可以改變某些元素的屬性。下面是對本章此前學習內(nèi)容的一個簡要總結(jié):  一份文檔就是一棵節(jié)點樹。  節(jié)點分為不同的類型:元素節(jié)點、屬性節(jié)點和文本節(jié)點等。  getElementById()方法將返回一個對象,該對象對應著文檔里的一個特定的元素節(jié)點。  getElementsByTagName()方法將返回一個對象數(shù)組,它們分別對應著文檔里的一個特定的元素節(jié)點。&

27、#160; 這些節(jié)點中的每個都是一個對象。接下來,我們將向大家介紹幾個與這些對象相關(guān)聯(lián)的屬性和方法。3.4.1getAttribute()方法至此,我們已經(jīng)向大家介紹了兩種檢索特定元素節(jié)點的辦法:一種是使用getElementById()方法,另一種是使用getElementsByTagName()方法。在找到那個元素后,我們就可以利用getAttribute()方法把它的各種屬性的值查詢出來。getAttribute()方法是一個函數(shù)。它只有一個參數(shù)你打算查詢的屬性的名字:不過,getAttribute()方法不能通過document對象調(diào)用,這與我們此前介紹過的其他方法不同。我們

28、只能通過一個元素節(jié)點對象調(diào)用它。例如,你可以把它與getElementsByTagName()方法結(jié)合起來,去查詢每個<p>元素的title屬性,如下所示:如果把上面這段代碼插入到前面給出的“購物清單”示例文檔的末尾,并在Web瀏覽器里重新加載這個頁面,屏幕上將彈出一個顯示著文本消息“a gentle reminder”的alter對話框。在“購物清單”文檔里只有一個帶有title屬性的<p>元素。假如這份文檔還有一個或更多個不帶title屬性的<p>元素,則相應的getAttribute("title")調(diào)用將返回null。null是J

29、avaScript語言中的空值,其含義是“你說的這個東西不存在”。如果你們想親自驗證一下這件事,請先把下面這段文本插入到“購物清單”文檔中的現(xiàn)有文本段落之后:然后重新加載這個頁面。這一次,你們將看到兩個alter對話框,而第二個對話框?qū)⑹且黄瞻谆蛘呤侵伙@示著單詞“null”具體情況要取決于你的Web瀏覽器將如何顯示null值??梢孕薷奈覀兊哪_本,讓它只在title屬性存在時才彈出一條消息。我們將增加一條if語句來檢查getAttribute()方法的返回值是不是null。趁著這個機會,我們還增加了幾個變量以提高腳本的可讀性:現(xiàn)在,如果重新加載這個頁面,你們將只會看到一個顯示著“a gentl

30、e reminder”消息的alter對話框,如下所示。我們甚至可以把這段代碼縮得更短一些。當檢查某項數(shù)據(jù)是否是null值時,我們其實是在檢查它是否存在。這種檢查可以簡化為直接把被檢查的數(shù)據(jù)用做if語句的條件。if (something)與if (something != null)完全等價,但前者顯然更為簡明。此時,如果something存在,則if語句的條件將為真;如果something不存在,則if語句的條件將為假。具體到這個例子,只要我們把if (title_text != null)替換為if (title_text),我們就可以得到更簡明的代碼。此外,為了進一步增加代碼的可讀性,我

31、們還可以趁此機會把alter語句與if語句寫在同一行上,這可以讓它們更接近于我們?nèi)粘I钪械挠⒄Z句子:3.4.2setAttribute()方法我們此前介紹給大家的所有方法都只能用來檢索信息。setAttribute()方法與它們有一個本質(zhì)上的區(qū)別:它允許我們對屬性節(jié)點的值做出修改。類似于getAttribute()方法,setAttribute()方法也是一個只能通過元素節(jié)點對象調(diào)用的函數(shù),但setAttribute()方法需要我們向它傳遞兩個參數(shù):在下面的例子里,第一條語句將把id屬性值是purchase的元素檢索出來,第二條語句將把這個元素的title屬性值設置為a list of go

32、ods:我們可以利用getAttribute()方法來證明這個元素的title屬性值確實發(fā)生了變化:上面這些語句將在屏幕上彈出兩個alert對話框:第一個alter對話框出現(xiàn)在setAttribute()方法被調(diào)用之前,它將是一片空白或顯示著單詞“null”;第二個出現(xiàn)在title屬性值被設置之后,它將顯示著“a list of goods”消息。在上例中,我們設置了一個現(xiàn)有節(jié)點的title屬性,但這個屬性原先并不存在。這意味著我們發(fā)出的setAttribute()調(diào)用實際完成了兩項操作:先把這個屬性創(chuàng)建出來,然后再對其值進行設置。如果我們把setAttribute()方法用在元素節(jié)點的某個現(xiàn)

33、有屬性上,這個屬性的當前值將被覆蓋。在“購物清單”示例文檔里,<p>元素已經(jīng)有了一個title屬性,這個屬性的值是a gentle reminder。我們可以用setAttribute()方法來改變它的當前值:上面這段代碼將先從文檔里把已經(jīng)帶有title屬性的<p>元素全部檢索出來,然后把它們的title屬性值全部修改為brand new title text。具體到“購物清單”文檔,屬性值a gentle reminder將被覆蓋。這里有一個非常值得關(guān)注的細節(jié):通過setAttribute()方法對文檔做出的修改,將使得文檔在瀏覽器窗口里的顯示效果和/或行為動作發(fā)生相

34、應的變化,但我們在通過瀏覽器的view source(查看源代碼)選項去查看文檔的源代碼時看到的仍將是原來的屬性值也就是說,setAttribute()方法做出的修改不會反映在文檔本身的源代碼里。這種“表里不一”的現(xiàn)象源自DOM的工作模式:先加載文檔的靜態(tài)內(nèi)容、再以動態(tài)方式對它們進行刷新,動態(tài)刷新不影響文檔的靜態(tài)內(nèi)容。這正是DOM的真正威力和誘人之處:對頁面內(nèi)容的刷新不需要最終用戶在他們的瀏覽器里執(zhí)行頁面刷新操作就可以實現(xiàn)。3.5小結(jié)在這一章里,我們向大家介紹了DOM提供的四個方法:  getElementById()方法  getElementsByT

35、agName()方法  getAttribute()方法  setAttribute()方法這四個方法是將要編寫的許多DOM腳本的基石。DOM還提供了許多其他的屬性和方法,如nodeName、nodeValue、chileNodes、nextSibling和parentNode等,但現(xiàn)在還不是它們出場的時候我打算在本書后面的有關(guān)章節(jié)中選擇一些適當?shù)臅r機把它們依次介紹給大家。我在這里列出它們的目的只是為了激起大家的學習興趣。本章內(nèi)容比較偏重于理論。在看過那么多的alter對話框之后,相信大家都迫不及待地想通過其他一些東西去進一步了解和測試DOM,而我也正想

36、通過一個案例來進一步展示DOM的強大威力。在下一章中,我將帶領(lǐng)大家利用本章介紹的四個DOM方法去創(chuàng)建一個基于JavaScript的圖片庫。第4章 案例研究:JavaScript美術(shù)館現(xiàn)在,是時候利用DOM去完成一些簡單的任務了。在這一章中,我將帶領(lǐng)大家用JavaScript和DOM去建立一個圖片庫,并將其稱為“JavaScript美術(shù)館”。我們將按照以下步驟來完成這一案例:  編寫一份優(yōu)秀的標記語言文檔。  編寫一個JavaScript函數(shù)以顯示用戶想要查看的圖片。  在標記語言文檔里觸發(fā)一個調(diào)用JavaScript圖片顯示的函數(shù)。&

37、#160; 對這個JavaScript函數(shù)的功能進行擴展。這需要用到幾個新的DOM方法。把一些圖片發(fā)布到網(wǎng)上的辦法很多。最容易想到的辦法是把所有的圖片都放到同一個網(wǎng)頁里。不過,如果你打算發(fā)布的圖片比較多的話,這個頁面很快就會因為變得過于巨大而失去吸引力。要知道,雖然這種網(wǎng)頁本身的HTML代碼不會多到哪兒去,但算上那些圖片可就不一樣了。我們必須面對的現(xiàn)實是:數(shù)據(jù)量越大,網(wǎng)頁的下載時間就越長,但愿意等待很長時間去下載一個網(wǎng)頁的人卻沒有幾個。因此,為每張圖片分別創(chuàng)建一個網(wǎng)頁的解決方案顯然更值得考慮。你的圖片庫將不再是一個體積龐大、難以下載的網(wǎng)頁,而是許多尺寸合理、便于下載和瀏覽的頁面。不過

38、,這一解決方案并非盡善盡美:首先,為每張圖片分別制作一個網(wǎng)頁需要花費不少的時間和精力;其次,需要在每個網(wǎng)頁上提供一些鏈接,來給出當前圖片在整個圖片庫里的位置以方便人們從當前圖片轉(zhuǎn)到其他的圖片。如果你想兩全其美,利用JavaScript來創(chuàng)建圖片庫將是最佳的選擇:把整個圖片庫的瀏覽鏈接集中安排在你的圖片庫主頁里,只在用戶點擊了這個主頁里的某個圖片鏈接時才把相應的圖片傳送給他。4.1編寫標記語言文檔為了完成“JavaScript美術(shù)館”案例,我特意用數(shù)碼相機拍攝了幾張照片,并把它們修整成最適合于用瀏覽器來查看的尺寸,即400像素寬×300像素高。第一項工作是為這些圖片創(chuàng)建一個鏈接清單。因

39、為我沒打算讓這些圖片按照某種特殊的順序排列,所以將使用一個無序清單元素(<ul>)來列出那些鏈接。如果想讓自己的圖片按順序排列的話,應該使用一個排序清單元素(<ol>)去組織圖片鏈接。下面就是我編寫出來的HTML文檔:我將把這份文檔保存為gallery.html文件,并把圖片集中保存在子目錄images里。我的images子目錄和gallery.html文件位于同一個子目錄下。在gallery.html文件里,無序清單元素中的每個鏈接分別指向不同的圖片。在瀏覽器窗口里點擊某個鏈接就可以轉(zhuǎn)到相應的圖片,但從圖片重新返回到鏈接清單目前還必須借助于瀏覽器的Back(后退)按鈕

40、。下面是這個基本的鏈接清單在瀏覽器窗口里的顯示效果。這是一個相當令人滿意的網(wǎng)頁,但它的默認行為還不太理想。下面是我覺得還需要改進的幾個地方:  當點擊某個鏈接時,我希望能留在這個網(wǎng)頁而不是轉(zhuǎn)到另一個窗口。  當點擊某個鏈接時,我希望能在這個網(wǎng)頁上同時看到那張圖片以及原有的圖片清單。下面是我為了實現(xiàn)上述希望而需要完成的幾項改進:   通過增加一個“占位符”圖片的辦法在這個主頁上為圖片預留一個瀏覽區(qū)域。  在點擊某個鏈接時,將攔截這個網(wǎng)頁的默認行為。  在點擊某個鏈接時,將把“占位符”圖片替換為與那

41、個鏈接相對應的圖片。我們先來解決“占位符”圖片的問題。我選用了一個類似于名片的圖片,你們可以根據(jù)個人喜好來決定選用的圖片,即使選用一個空白圖片也沒問題。把下面這些代碼插入到圖片名單的末尾:我對這個圖片的id屬性進行了設置,這將使我可以通過一個外部的樣式表對圖片的顯示位置和顯示效果加以控制。例如,我可以讓這個圖片出現(xiàn)在鏈接清單的旁邊而不是它的下方。我還可以在自己的JavaScript代碼里使用這個id值。下面是這個頁面在增加了“占位符”圖片后的顯示效果?,F(xiàn)在,我的HTML文檔已經(jīng)準備好了。接下來的工作是編寫一些必要的JavaScript代碼。4.2編寫JavaScript函數(shù)為了把“占位符”圖片

42、替換為想要查看的圖片,需要改變它的src屬性。setAttribute()方法是完成這項工作的最佳選擇,而我將利用這個方法寫一個函數(shù)。那個函數(shù)只有一個參數(shù),即我想查看的那張圖片的鏈接;它將通過改變“占位符”圖片的src屬性的辦法將其替換為我想查看的那張圖片。首先,需要給函數(shù)起一個好的名字。我想讓它既能提醒我這個函數(shù)的用途,又足夠簡明扼要。我決定把這個函數(shù)命名為showPic()。還需要給這個函數(shù)的參數(shù)起一個名字,我決定把它命名為whichpic:whichpic代表著一個元素節(jié)點;具體地說,那將是一個指向某個圖片的<a>元素。我需要知道那個圖片的文件路徑,這個路徑可以通過在whic

43、hpic元素上調(diào)用getAttribute()方法的辦法查出來只要把"href"作為參數(shù)傳遞給getAttribute()方法,就可以知道那個圖片的文件路徑了:我將把這個路徑存入一個變量以便在后面的語句里使用它。我決定把這個變量命名為source:接下來,還需要把“占位符”圖片檢索出來,這種事對getElementById()方法來說不過是小菜一碟: 我不想重復敲入“document. getElementById("placerholder")”這么長的字符串,所以將把這個元素賦值給一個變量并將其命名為placerholder:現(xiàn)在,已經(jīng)聲明并賦值了兩

44、個變量:source和placerholder。它們可以讓我的腳本簡明易讀。我將使用setAttribute()方法對placerholder元素的src屬性進行刷新。還記得嗎,這個方法有兩個參數(shù):一個是打算對之進行設置的屬性,另一個是這個屬性的新屬性值。具體到這個例子,因為我想對src屬性進行設置,所以第一個參數(shù)是"src";至于第二個參數(shù),也就是src屬性的新屬性值,我已經(jīng)把它保存在source變量里了:這顯然要比下面這么冗長的代碼更容易閱讀和理解:4.2.1DOM之前的解決方案其實,不使用setAttribute()方法也可以改變某個圖片的src屬性。setAttri

45、bute()方法是“第1級DOM”(DOM Level 1)的組成部分之一,這個方法可以對任意元素節(jié)點的任意屬性進行設置。在“第1級DOM”出現(xiàn)之前,程序員只能通過另外一種辦法對一部分元素的屬性進行設置,這個辦法至少在目前還可以用來改變某些屬性的值。例如,如果想改變某個輸入元素的value屬性,可以使用如下所示的辦法:這與下面這條語句的效果是等價的:類似的辦法也可以用來改變圖片的src屬性。例如,在我的圖片庫腳本里,完全可以用下面這條語句來代替setAttribute()調(diào)用:我個人更喜歡使用setAttribute()方法。這起碼可以讓我不必費心去記憶哪些元素的哪些屬性可以用哪些DOM之前的

46、方法去設置。雖然用那些老辦法可以毫無問題地對文檔里的圖片、表單和其他一些元素的屬性進行設置,但setAttribute()方法的優(yōu)勢在于它可以對文檔中的任何一個元素的任何一個屬性做出修改。“第1級DOM”的另一個優(yōu)勢是可移植性更好。那些老方法只適用于Web文檔,DOM則適用于任何一種標記語言。雖然這種差異對我們這個例子沒有影響,但我希望大家能夠牢牢記住這一點:DOM是一種適用于多種環(huán)境和多種程序設計語言的通用型API。如果想把從本書學到的DOM技巧運用在Web瀏覽器以外的應用環(huán)境里,嚴格遵守“第1級DOM”能夠讓你們避免與兼容性有關(guān)的任何問題。4.2.2showPic()函數(shù)的代碼清單下面是s

47、howPic()函數(shù)完整的代碼清單:接下來的任務是把這個JavaScript函數(shù)與我們的HTML文檔結(jié)合起來。4.3JavaScript函數(shù)的調(diào)用我需要把剛編寫出來showPic()函數(shù)與圖片庫HTML文檔結(jié)合起來。最簡單的辦法是把這個函數(shù)用一組<script>標簽插入到那個文檔的<head>部分,但我認為這種做法有點兒目光短淺:如果今后想把這同一函數(shù)用在多個頁面上的話,我將不得不反復多次地進行剪貼操作。為今后考慮,更有遠見的辦法是先把這個函數(shù)存入一個外部文件,然后在每一份需要用到這個函數(shù)的HTML文檔的<head>部分插入一個鏈接來引用這個外部文件。以.j

48、s作為文件擴展名,把這個函數(shù)存入一個文本文件。完全可以把這種文件命名為你們喜歡的任何東西,但我習慣于用這些文件所包含的函數(shù)的名字來命名它們我給這個文件起的名字是showPic.js。就像我剛才決定把所有的圖片集中存放在images子目錄里那樣,把所有的JavaScript腳本文件集中存放在一個子目錄里也將是個好主意。我創(chuàng)建了一個名為scripts的子目錄并把showPic.js文件保存到其中?,F(xiàn)在,需要在圖片庫HTML文檔里插入一個鏈接來引用這個JavaScript腳本文件。我將把下面這條語句插入那份HTML文檔的<head>部分(選擇的插入位置是<head>標簽之后)

49、:有了這條語句,把showPic()函數(shù)與圖片庫HTML文檔結(jié)合起來的任務就已經(jīng)完成了一半我還需要為HTML文檔里的每個圖片鏈接增加一個函數(shù)調(diào)用動作,否則showPic()函數(shù)將永遠也不會被調(diào)用。我將通過增加一個事件處理函數(shù)(event handler)的辦法來完成這項工作。事件處理函數(shù)事件處理函數(shù)的作用是,在預定事件發(fā)生時讓預先安排好的JavaScript代碼開始執(zhí)行,用術(shù)語來說就是 “觸發(fā)一個動作”。例如,如果想在鼠標指針懸停在某個元素上時觸發(fā)一個動作,就需要使用onmouseover事件處理函數(shù);如果想在鼠標指針離開某個元素時觸發(fā)一個動作,就需要使用onmouseout事件處理函數(shù)。在“

50、JavaScript美術(shù)館”案例里,我想在用戶點擊某個鏈接時觸發(fā)一個動作,所以需要使用onclick事件處理函數(shù)。我想通過onclick事件處理函數(shù)去觸發(fā)的動作是調(diào)用showPic()函數(shù),而要想調(diào)用這個函數(shù),就必須向它傳遞一個參數(shù):一個帶有href屬性的元素節(jié)點。在圖片庫HTML文檔里,當我把onclick事件處理函數(shù)嵌入一些鏈接時,我需要把那些鏈接本身用作showPic()函數(shù)的參數(shù)。有個非常簡單但又非常有效的辦法可以做到這一點:使用JavaScript語言中的this關(guān)鍵字。這個關(guān)鍵字的含義是“這個對象”。具體到正在討論的這個例子,我將使用this來表示“這個<a>元素節(jié)點”

51、:綜上所述,我將使用onclick事件處理函數(shù)去調(diào)用showPic(this)方法。使用事件處理函數(shù)調(diào)用JavaScript代碼的語法如下所示:請注意,在如上所示的語法里,JavaScript代碼是包含在一對引號之間的:我們可以把任意數(shù)量的JavaScript語句放在這對引號之間,只要把各條語句用分號隔開即可。下面這條語句將完成“使用onclick事件處理函數(shù)調(diào)用showPic(this)方法”的任務:不過,如果只把上面這個事件處理函數(shù)插入到HTML文檔中的鏈接里去的話,將遇到這樣一個問題:在onclick事件發(fā)生時,不僅showPic(this)函數(shù)將被調(diào)用,鏈接被點擊時的默認行為也將發(fā)生。

52、這意味著用戶還是會被帶到另外一個圖片查看窗口里去,而這是我不希望發(fā)生的事情。我需要阻止這種默認行為的發(fā)生。要想達到這一目的,我們必須對事件處理函數(shù)的工作機制有進一步的了解:在給某個元素添加了事件處理函數(shù)后,一旦發(fā)生預定事件,相應的JavaScript代碼就會得到執(zhí)行;那些JavaScript代碼可以返回一個結(jié)果,而這個結(jié)果將被傳遞回那個事件處理函數(shù)。例如,我們可以給某個鏈接添加一個onclick事件處理函數(shù),并讓這個處理函數(shù)所觸發(fā)的JavaScript代碼返回布爾值true或false。這樣一來,當這個鏈接被點擊時,如果那段JavaScript代碼返回給onclick事件處理函數(shù)的值是true

53、,onclick事件處理函數(shù)將認為“這個鏈接被點擊了”;反之,如果那段JavaScript代碼返回給onclick事件處理函數(shù)的值是false,onclick事件處理函數(shù)將認為“這個鏈接沒有被點擊”??梢酝ㄟ^下面這個簡單測試去驗證這一結(jié)論:當點擊這個鏈接時,因為onclick事件處理函數(shù)所觸發(fā)的JavaScript代碼返回給它的值是false,所以這個鏈接在被點擊時的默認行為將不會發(fā)生。同樣道理,如果像下面這樣在onclick事件處理函數(shù)所觸發(fā)的JavaScript代碼里增加一條return false語句的話,我就可以不讓用戶被他們所點擊的鏈接帶到另外一個圖片查看窗口里去:下面是最終完成的o

54、nclick事件處理函數(shù)在圖片庫HTML文檔里的樣子:接下來,只要在圖片庫HTML文檔里把這個onclick事件處理函數(shù)添加到每個鏈接上即可。這當然有些麻煩,但眼下只能這么做我將在后面的內(nèi)容里向大家介紹一個可以避免這種麻煩的辦法。下面是圖片庫HTML文檔在我以手動方式把這個onclick事件處理函數(shù)添加到各個有關(guān)鏈接上之后的樣子:現(xiàn)在,如果把這個頁面加載到Web瀏覽器里,你們將看到一個能夠正常工作的“JavaScript美術(shù)館”:在如下所示的頁面里,不管在圖片列表里的哪個鏈接上點擊鼠標,都將在這同一個頁面里看到相應的圖片。4.4對JavaScript函數(shù)進行功能擴展在同一個網(wǎng)頁上切換顯示不同的

55、圖片并不是什么新鮮事。有著這類效果的網(wǎng)頁和腳本早在W3C推出它們的標準化DOM和JavaScript語言之前就已經(jīng)出現(xiàn)了,如今更是得到了廣泛的流行。在這種情形下,如果你們想讓自己與眾不同,就必須另辟蹊徑你們有沒有想過在同一個網(wǎng)頁上切換顯示不同的文本?我可不是在開玩笑,利用JavaScript語言和DOM,確實可以做到這一點。圖片庫HTML文檔里的每個圖片鏈接都有一個title屬性。我想把這個屬性的值提取出來并讓它們伴隨相應的圖片一同顯示在網(wǎng)頁上。title屬性的值可以用getAttribute()方法輕而易舉地提取出來,如果把下面這條語句添加到showPic()函數(shù)的開頭的話,就可以把titl

56、e屬性的值保存到一個變量里:解決了提取title屬性值的問題,還需要把它插入到HTML文檔中的適當位置。為了完成這一工作,我需要用到幾個新的DOM屬性。4.4.1childNodes屬性childNodes屬性讓我們可以從給定文檔的節(jié)點樹里把任何一個元素的所有子元素檢索出來。childNodes屬性將返回一個數(shù)組,這個數(shù)組包含給定元素節(jié)點的全體子元素:假設我們需要把某個文檔的body元素的全體子元素檢索出來。首先,我們將使用getElementsByTagName()方法來得到body元素。因為每份文檔只有一個body元素,所以它將是getElementsByTagName("bod

57、y")方法所返回的數(shù)組中的第一個(也是唯一一個)元素:現(xiàn)在,變量body_element已經(jīng)指向了那個文檔的body元素。接下來,可以用如下所示的語法記號把body元素的全體子元素檢索出來:寫出這個記號顯然要比敲入下面這個長長的字符串要簡明得多:順便說一句,body元素還有一個更簡單的專用記號:現(xiàn)在,已經(jīng)知道如何把body元素的全體子元素檢索出來了,我們來看看這些信息的用途。首先,我們可以精確地查出body元素有多少個子元素。因為childNodes屬性返回的是一個數(shù)組,所以可以用數(shù)組數(shù)據(jù)類型的length屬性查出它所包含的元素的個數(shù):請把下面這個小函數(shù)添加到showPic.js文件

58、里:這個簡單的小函數(shù)將彈出一個alert對話框,其顯示內(nèi)容是body元素的子元素的總數(shù)。我想讓這個函數(shù)在頁面加載時執(zhí)行,而這需要使用onload事件處理函數(shù)。把下面這條語句添加到代碼段的末尾:這條語句將在頁面加載時調(diào)用countBodyChildren函數(shù)。在Web瀏覽器里刷新gallery.html文件。你們將看到一個alert對話框,其顯示內(nèi)容是body元素的子元素的總數(shù)。那個數(shù)字很可能會讓你們大吃一驚。4.4.2nodeType屬性根據(jù)gallery.html文件的結(jié)構(gòu),body元素應該只有3個子元素:一個h1元素、一個ul元素和一個imag元素??墒?,countBodyChildren

59、()函數(shù)給出來的數(shù)字卻遠大于此。之所以會這樣,是因為文檔樹的節(jié)點類型并非只有元素節(jié)點一種。由childNodes屬性返回的數(shù)組包含著所有類型的節(jié)點,除了所有的元素節(jié)點,所有的屬性節(jié)點和文本節(jié)點也包含在其中。事實上,文檔里幾乎每一樣東西都是一個節(jié)點甚至連空格和換行符都會被解釋為節(jié)點,而它們也全都包含在childNodes屬性所返回的數(shù)組當中。因此,countBodyChildren()函數(shù)的返回結(jié)果才會是一個相當大的數(shù)字。還好,我們可以利用nodeType屬性來區(qū)分文檔里的各個節(jié)點。這個屬性可以讓我們知道自己正在與哪一種節(jié)點打交道。不過,這個屬性返回的是一個數(shù)字而不是像“element”或“attribute”那樣的英文字符串。下面是nodeType屬性的調(diào)用語法:為了驗證這一點,請把countBodyChildren()函數(shù)中的alter語句替換為下面這條語句,這樣一來,我們就可以知道body_element元素的nodeType屬性了:在Web瀏覽器里刷新gallery.html文件,將看到一個顯示數(shù)字“1”的alert對話框。換句話說,元素節(jié)點的nodeType屬性值是1。nodeType屬性總共有12種可取值,但其中僅有3種具有實用價值:元素節(jié)點、屬性節(jié)點和文

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論