大家好差油,我是IT修真院上海分院1期的Web學員劉洪利抚笔,今天給大家分享一下關(guān)于JavaScript中常見的DOM操作
1.背景介紹
????????什么是DOM崭参?簡單地說整慎,DOM是一套對文檔的內(nèi)容進行抽象和概念化的方法
????????在現(xiàn)實世界里声诸,人們對所謂的'世界對象模型'都不會陌生酱讶,例如,當用'汽車'彼乌、'房子'和'樹'等名詞來稱呼日常生活環(huán)境里的事物時泻肯,我們都可以百分百的肯定對方知道我們說的是什么,這是因為人們在對這些名詞所代表的的東西有著相同的認知慰照。于是赡突,當對別人說"汽車停在車庫里"時前鹅,可以斷定他們不會理解為"小鳥關(guān)在壁櫥里"
????????我們的"世界對象模型"不進可以用來描述客觀存在的事物妙黍,還可以同來描述抽象概念衰伯。例如,假設(shè)有個人想我問路墅垮,而我給出的答案是"左邊第三棟房子"惕医,這個答案有沒有意義取決于那個人能夠理解"左邊"和"第三"的含義。如果他不會數(shù)數(shù)或者分不清左右算色,則不管他是否理解這幾個概念抬伺,我的回答對他都不會有任何的幫助。在現(xiàn)實世界中灾梦,正是因為大家對抽象的"世界對象模型"有著基本的共識峡钓,人們才能用非常簡單的話來表達出復雜的含義并得到對方的理解。
????????而DOM的定義則是由W3C所制定的標準若河,定義為"一個與系統(tǒng)平臺和編程語言無關(guān)的接口椒楣,程序和腳本可以通過這個接口動態(tài)地訪問和修改文檔的內(nèi)容`、結(jié)構(gòu)和樣式牡肉。"
2.知識剖析
? ? ? ? 2.1. 節(jié)點是什么
????????節(jié)點這個詞是一個網(wǎng)絡用語,代表了網(wǎng)絡中的一個連接點淆九。一個網(wǎng)絡就是由一些節(jié)點構(gòu)成的集合统锤。
????????在現(xiàn)實世界中,一切事物都由原子構(gòu)成炭庙。原子就是現(xiàn)實世界的節(jié)點饲窿。但是原子同樣還可以進一步分解為更細小的亞原子微粒。這些亞原子微粒同樣也是節(jié)點焕蹄。
????????DOM也是同樣的情況逾雄。文檔是由節(jié)點構(gòu)成的集合,只不過此時的節(jié)點是文檔樹上的樹枝和樹葉而已。
????????在DOM中有許多不同類型的節(jié)點鸦泳。就像原子包含著亞原子微粒那樣银锻,也有很多類型的DOM節(jié)點包含著其他類型的節(jié)點。接下來我們先看看其中的三種:元素節(jié)點做鹰、文本節(jié)點和屬性節(jié)點击纬。
????????2.2. 元素節(jié)點
????????在DOM中的原子就是元素節(jié)點。
????????像是我們現(xiàn)在所看到的這個網(wǎng)頁钾麸,我們在編寫時更振,會用到諸如<body>、<head>饭尝、<p>這些元素肯腕。如果把Web上的文檔比作一座大廈,那么元素就是建造這座大廈的磚塊钥平,這些元素在在文檔中的布局形成了文檔的結(jié)構(gòu)实撒。元素可以包含其他的元素,在我們所看到的頁面頁中帖池,內(nèi)容都被包含在在一個<section>元素的內(nèi)部奈惑。而唯一沒有被包含在其他元素中的唯一元素是'<html>',他和我們的節(jié)點樹的根元素睡汹,其他的所有元素都被包含在'<html>'中肴甸。
? ? ? ? 2.3. 文本節(jié)點
????????元素節(jié)點只是節(jié)點類型的一種。如果一份文檔完全有一些空白元素構(gòu)成囚巴,他將有一個結(jié)構(gòu)原在,但這份文檔本身將不會包含什么內(nèi)容。
????????在我們的ppt首頁中彤叉,'<p>'元素包含著文本庶柿,'分享人:劉洪利'。他就是一個文本節(jié)點秽浇。在html文檔里浮庐,文本節(jié)點總是被包含在元素節(jié)點的內(nèi)部。
? ? ? ? 2.4. 屬性節(jié)點
????????屬性節(jié)點用來對元素做出更具體的描述柬焕。例如审残,幾乎所有的元素都有一個title屬性,而我們可以利用這個屬性對包含在元素里的東西做出準確的描述:'<p title="a gentle reminder">這是一個帶有溫馨提示的p標簽</p>'
????????在DOM中斑举,title="a gentle reminder"是一個屬性節(jié)點搅轿。因為屬性總是被放在起始標簽里,所以屬性節(jié)點總是被包含在元素節(jié)點中富玷。并非所有的標簽都包含著屬性璧坟,但是所有的屬性都被元素包含既穆。
? ? ? ? 2.5. 常見的DOM操作
獲取DOM
????????通過使用 getElementById() 方法匹配元素的id屬性來訪問元素節(jié)點,對元素節(jié)點進行操作
????????通過使用 getElementsByTagName() 方法匹配元素的tagName來訪問元素節(jié)點雀鹃,對元素節(jié)點進行操作
????????通過使用 getElementsByClassName() 方法匹配元素的className來訪問元素節(jié)點幻工,對元素節(jié)點進行操作
????????值得注意的是, getElementsByTagName() 和 getElementsByClassName() 這兩種方法因為其訪問的是節(jié)點中的可能為復數(shù)的屬性褐澎,所以得到的會是一個以數(shù)組的形式來體現(xiàn)出來的元素節(jié)點集合会钝,我們可以通過打印獲取到的DOM節(jié)點來判斷類型
DOM事件
????????onclick事件---當用戶點擊時執(zhí)行
????????onload事件---當用戶進入時執(zhí)行
????????onunload事件---用用戶離開時執(zhí)行
????????onmouseover事件---當用戶鼠標指針移入時執(zhí)行
????????onmouseout事件---當用戶鼠標指針移出時執(zhí)行
????????onmousedown事件---當用戶鼠標摁下時執(zhí)行
????????onmouseup事件---當用戶鼠標松開時執(zhí)行
? ??????????????????????????????????????????????????????????????????????????????????????????????????????demo
3. 常見問題
如何通過class和tag調(diào)用元素?如何對其設(shè)置屬性?
4.解決方案
在一個頁面中常常有多個class相同的元素工三,也有多個標簽相同的元素迁酸,在調(diào)用時方法如下
5. 擴展思考
????????onblur事件---當對象失去焦點時發(fā)生
????????onchange事件---當對象域的值被改變時發(fā)生
????????button 事件---屬性可返回一個整數(shù),指示當事件被觸發(fā)時哪個鼠標按鍵被點擊俭正。
????????更多的事件就不一一的描述了奸鬓,有興趣的同學可以去看下這個
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?w3school
6. 參考文獻
書籍:《JavaScript DOM編程藝術(shù)》
網(wǎng)址:w3school
7.更多討論
? ? ? ? ? ? Q:dom操作是異步的嗎
? ? ? ? ? ? A:dom的操作其實是同步的,但是渲染是異步的掸读。因為JavaScript引擎線程跟GUI渲染線程是互斥的串远,即我執(zhí)行的時候,你就靠邊站儿惫,我執(zhí)行完你才能執(zhí)行澡罚。具體的可以看下這篇文章https://segmentfault.com/a/1190000005803237----《關(guān)于修改DOM是異步還是同步的問題》
? ? ? ? ? ? Q:除了getElementsByClassName()、getElementsByTagName()肾请、getElementById()還有什么可以獲取dom節(jié)點的方法
? ? ? ? ? ? A:
1.通過節(jié)點屬性得到元素
????????????????????1)node屬性:來獲取節(jié)點的名稱留搔、類型、值铛铁。
js代碼:
????????????????????window.onload=function(){ 子節(jié)點
????????????????????????var pox = document.getElementById('pox');
????????????????????????alert(pox.childNodes.length) //子節(jié)點數(shù)量
????????????????????????alert(pox.childNodes[0].nodeValue); // 第一個子節(jié)點的內(nèi)容
????????????????????????alert(pox.firstChild.nodeValue);? // 第一個子節(jié)點的內(nèi)容
????????????????????????alert(pox.lastChild.nodeValue); // 最后一個節(jié)點的內(nèi)容
????????????????????};
????????注意:node只能獲取當前節(jié)點的東西隔显,在上面的js代碼中node本身把節(jié)點指針放在元素上,所以本身沒有value值饵逐,
2.層次節(jié)點屬性:層級節(jié)點可以分為父子節(jié)點和兄弟節(jié)點括眠,通過當前節(jié)點可以獲取其他層次的節(jié)點。
????????2.1)子節(jié)點childNodes倍权、第一個字節(jié)點firstChilds掷豺、最后一個子節(jié)點lastChilds。
js代碼:
? ??????window.onload=function(){ 子節(jié)點
????????????var pox = document.getElementById('pox');
????????????alert(pox.childNodes.length) //子節(jié)點數(shù)量
????????????alert(pox.childNodes[0].nodeValue); // 第一個子節(jié)點的內(nèi)容
????????????alert(pox.firstChild.nodeValue);? // 第一個子節(jié)點的內(nèi)容
????????????alert(pox.lastChild.nodeValue); // 最后一個節(jié)點的內(nèi)容
????????};
? ??????2.2)父節(jié)點parentChild薄声、兄弟節(jié)點previousSibing,nextSibing当船。
js代碼:
????????window.onload=function(){ 父節(jié)點,上下節(jié)點
????????????var pox = document.getElementById('pox');
????????????alert(pox.parentNode);? ? //pox節(jié)點的父節(jié)點body節(jié)點
????????????alert(pox.firstChild.nextSibling);? ? //pox節(jié)點的子節(jié)點中第一個節(jié)點的下一個節(jié)點
????????????alert(pox.lastChild.previousSibling);? //pox節(jié)點的子節(jié)點中最后一個節(jié)點的上一個節(jié)點
????????????alert(pox.lastChild.previousSibling.nodeName)
????????};
本回答摘自-----------《獲取元素節(jié)點(DOM基礎(chǔ) )》http://blog.csdn.net/u010928364/article/details/43935875
? ? ? ? ? ? Q:dom操作的最佳實踐應該是什么樣的
? ? ? ? ? ? A:
????????????????????1. 平穩(wěn)退化:正確的使用JavaScript腳本奸柬,讓訪問者在他們?yōu)g覽器不支持JavaScript的情況下仍能順利的瀏覽你的網(wǎng)站,即是有些功能無法使用婴程,但最基本的操作仍能順利完成廓奕。
? ? ? ? ? ? ? ? ? ? 2. 分離JavaScript:將HTML內(nèi)部DOM事件分離到外部來,保證HTML的純凈,同時可以在外部js文件通過獲取DOM節(jié)點來給這個節(jié)點添加事件的形式來運行外部JavaScript文件桌粉。
? ? ? ? ? ? ? ? ? ? 3. 向后兼容:因為不同瀏覽器對JavaScript的支持程度也不一致蒸绩,絕大多數(shù)的瀏覽器都可以或多或少的支持JavaScript,铃肯,但比較古老的瀏覽器卻很有可能無法理解DOM提供的方法和腳本患亿。因此,我們通過以下幾點來確保那些古老的瀏覽器不會因為腳本代碼而出問題押逼。
? ? ? ? ? ? ? ? ? ? ? ? ????3.1. 對象檢測:檢測瀏覽器對JavaScript的支持程度步藕。我們可以通過將某種方法打包在一個if語句中,然后根據(jù)這條語句的條件表達式的求值結(jié)果為true(這個方法存在)還是false(這個方法不存在)來決定應該采取怎么樣的行動挑格。
? ? ? ? ? ? ? ? ? ? ? ? ????例如咙冗,如果有一個使用了getElementById()方法的函數(shù)么就可以在調(diào)用getElementById()方法之前先檢查用戶所用的瀏覽器是否支持這個方法。在使用對象檢查時漂彤,一定要刪除方法名后面的圓括號雾消,如果不刪掉,測試的將是方法的結(jié)果挫望,無論方法是否存在
? ? ? ? ? ? ? ? ? ? ? ? ? ? 代碼:
if( ! document.getElementById ) return false立润;
????????????????????4. 性能考慮: 為保證應用流暢的運行,在為文檔編寫和應用腳本時媳板,需要注意一些問題桑腮。
? ? ? ? ? ? ? ? ? ? ? ? ? ? 4.1. 盡量少訪問DOM和盡量減少標記
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 訪問DOM的方式對腳本性能會產(chǎn)生很大的影響。例如當我們需要訪問html頁面中所有的div元素來找到我們想要的那個節(jié)點拷肌,我們不知道會有多少div元素來面對著我們到旦,所以瀏覽器會去搜索整個DOM樹,從中查找可能匹配的元素巨缘。
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 另一個是盡量減少文檔中的標記數(shù)量添忘。過多不必要的元素只會增加DOM樹的規(guī)模,進而增加遍歷DOM樹以查找特定元素的時間若锁。
????????????????????????????4.2. 合并和放置腳本
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 我們通過合并外部JavaScript文件來減少加載頁面時發(fā)送的請求數(shù)量搁骑。減少請求數(shù)量通常都是在性能優(yōu)化時優(yōu)先考慮的。
? ? ? ? ? ? ? ? ? ? ? ? ? ? 4.3. 壓縮腳本
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 通過將腳本文件中不必要耳朵字節(jié)又固,如空格和注釋統(tǒng)統(tǒng)刪除仲器,從而達到“壓縮文件”的目的。
鳴謝
感謝大家觀看
分享人:劉洪利
IT修真院上海Web第1期學員劉洪利: 邀請碼14898047