一篇文章搞懂DOM
學習JavaScript肯定是會遇到DOM操作,那麽什麽是DOM?它又是幹嘛用的?這篇文章為你揭曉答案。
DOM是document object model的縮寫,簡稱文檔對象模型。
簡單的說DOM是一套對文檔的內容進行抽象和概念化的方法。我們可以把HTML文檔模型化,當作對象來處理。
基本概念:
文檔(document): HTML或XML文件。
節點(node):HTML文檔中的所有內容都可以稱之為節點,常見的節點有 元素節點 屬性節點 文本節點 註釋節點。
元素(element): HTML文檔中的標簽可以稱為元素。
我們可以把一個HTML文檔看做一個樹形結構的對象,每一個標簽會形成一個分支,這樣就很容易理解了,如下圖所示(圖片來自
知道了什麽是DOM,肯定要問DOM有什麽用?
DOM把HTML文檔抽象成一個對象,肯定是為了方便使用JavaScript對HTML文檔進行操作。DOM的作用就是為了對頁面的結構內容進行操作,增加頁面的動態特性。
好了,知道了DOM是幹嘛用的,那麽下面我們就學習如何進行DOM操作。
DOM操作主要分四個部分:
1、獲取HTML節點及修改節點的屬性
2、修改節點的樣式
3、給節點綁定事件
4、節點操作
現在我們進行一一介紹
獲取HTML節點與修改節點屬性(包含表單元素)
DOM提供了三個獲取節點的方法
方法一:
getElementById() //根據id屬性獲取一個DOM對象,區分大小寫,符合代碼規範
通過id尋找一個元素(找到的是一個元素對象) 該方法只能被document對象調用(同一個文檔中id不能重復)。
<div id="box"></div>
var box = document.getElementById(“box”);
方法二:
getElementsByTagName() //根據標簽返回多個DOM對象
通過標簽名尋找一類元素(找到的是由元素對象組成的偽數組) 即可以被document調用,又可以被元素對象調用,被元素對象調用時表示在該元素對象內部執行查找。
通常針對多個標簽,而且常會要用到for循環。
<div class="cl" id=“cl”> <div class="cl2"></div> <div class="cl2"></div> </div> <div class="cl"></div> <div class="cl"></div> vardivs = document.getElementsByTagName("div");// 獲取頁面上所有div,divs是一個偽數組 var cl = document.getElementById("cl");// 獲取id為cl的元素 var cl2s = cl.getElementsByTagName("div");// 獲取cl元素下面所有的div標簽,cl2s是一個偽數組
方法三:
getElementsByClassName()
通過類名尋找一類元素。
<div class="cl" id=“cl”> <p class="cl"></div> <span class="cl"></div> </div> <a class="cl"></a> var cls = document.getElementsByClassName("cl");//獲取到的是一個偽數組,裏面裝的是div p span a這四個元素對象
獲得到了節點元素後我們就可以對節點元素的屬性進行修改了。
DOM也提供了兩個方法供我們獲取和修改元素的屬性值。
getAttribute()
getAttribute是一個函數,用於獲取節點屬性。它只有一個參數,即所需要查詢的屬性的名字。getAttribute不屬於document對象,所有不能通過document對象調用,只能通過元素節點對象調用。
<div id="box" title=hello></div>
var box = document.getElementById(“box”); console.log(box.getAttribute(“title”));
通過這個方法我們可以獲取元素box的title屬性值為hello。
setAttribute()
setAttribute也是一個函數,用於修改節點屬性。與getAttribute用法類似,不同的地方在於它有兩個參數,第一個為屬性名,第二個參數為設定的屬性值。
<div id="box" title=hello></div> var box = document.getElementById(“box”); console.log(box.setAttribute(“title”,”world”));
此時,box節點的title屬性值已經變為world。
是不是感覺so easy.
其實還有更為簡便的方法來修改屬性值,直接使用點語法就可以了。
獲取屬性值
var 變量=box.title;
修改屬性值
box.屬性名 = “屬性值”;
是不是感覺更簡單呢。
在此我只舉例了title屬性,當然元素的屬性還有很多,比如img標簽的src屬性,我們可以更改src屬性來切換圖片。還可以設置表單元素的屬性
type可以設置input元素的類型;
value可以設置input元素的值;
checked可以設置input元素是否選中;
selected 可以設置下拉列表select中的option是否被選中;
disabled 可以設置input元素是否被禁用。
好了,屬性的操作就到此為止。
獲取節點與控制樣式
關於節點的獲取,上面只用到了三個方法,但是實際的項目HTML文檔往往是很復雜的,
文檔中所有的節點之間都存在這樣或那樣的關系。節點間的各種關系可以用傳統的家族關系來描述,相當於把文檔樹比喻成家譜。在 HTML 中,可以將<body>元素看成是<html>元素的子元素;相應地,也就可以將<html>元素看成是<body>元素的父元素。而<head>元素,則可以看成是<body>元素的同胞元素,因為它們都是同一個父元素<html>的直接子元素。
首先我們來認識一下文檔的層級結構,都有那些關系。
childNodes //子節點
children //子元素 雖然不是早期DOM標準中的方法,但是所有瀏覽器都支持
nextSibling //下一個兄弟節點
nextElementSibling //下一個兄弟元素 有兼容性問題
previousSibling//上一個兄弟節點
previousElementSibling //上一個兄弟元素 有兼容性問題
firstChild //第一個節點
firstElementChild //第一個子元素 有兼容性問題
lastChild //最後一個子節點
lastElementChild //最後一個子元素 有兼容性問題
parentNode //父節點 (一定是元素節點,所以無需處理)
所有獲取節點相關屬性都沒有兼容性問題
註意:節點和元素不是同一個概念,文章開頭說過,在此提醒一下。
獲取子節點&子元素
- childNodes: 獲取指定元素的子節點,包括文本節點、元素節點等
- children: 獲取知道元素的子元素,只會獲取元素節點。<ul id="list">
<li><a href="javascript:void(0)">首頁</a></li> <li><a href="javascript:void(0)">播客</a></li> <li><a href="javascript:void(0)">博客</a></li> <li><a href="javascript:void(0)">相冊</a></li> <li><a href="javascript:void(0)">關於</a></li> <li><a href="javascript:void(0)">幫助</a></li> </ul>
<script> var ul = document.getElementById("list"); var lis = ul.getElementsByTagName("li"); //不關心層級 只找指定標簽 //缺點: 如果內部還有li 也會找到 var nodes = ul.childNodes; //子節點 只找子級 //缺點: 除了我們想要的元素節點 還會獲取到其他節點 var children = ul.children;//子元素
</script>
childNodes是DOM標準中規定的方法 獲取節點的方式所有瀏覽器都支持
children不是DOM標準中規定的方法 因為很常用所有瀏覽器也都支持
在實際應用中,基本都是用children。
獲取下一個兄弟節點
nextSibling:下一個兄弟節點
<input type="text" id="txtName"> <span></span> <input type="text" id="txtPwd"><span></span> <input type="button" id="btn" value="註冊"> <script> var txt = document.getElementById("txtName"); var next = txt.nextSibling;// 獲取到的是換行,空文本節點 var pwd = document.getElementById("txtPwd"); var next = pwd.nextSibling;// 獲取到的是span元素,因為兩個標簽間沒有其他節點 </script>
獲取下一個兄弟元素
nextElementSibling: 下一個兄弟元素
<input type="text" id="txtName"> <span></span> <script> var txt = document.getElementById("txtName"); var next = txt.nextElementSibling;// 可以獲取到span元素,只獲取下一個兄弟元素,忽略非元素類型的節點 </script>
獲取父節點
parentNode: 獲取元素的父節點,父節點肯定是一個元素
<div id = "box"> <img src="1.jpg" id="img"/> </div> <script> var img = document.getElementById("img"); var parent = img.parentNode; //獲取到的就是id為box的div元素 </script>
節點的獲取我就先介紹到這裏,關於兼容性的問題我會再做補充。
下面看一下如何進行節點的樣式操作。
獲取樣式
- 通過style只能獲取行內樣式
- 獲取的樣式如果有單位,獲取到的樣式中也會帶單位,類型是一個字符串
設置樣式
1、通過style設置樣式
- 通過style設置的是行內樣式
- 如果樣式需要單位,設置時也需要把單位帶上
div{ width:100px; height:100px; } <div id="box"></div> var box = document.getElementById("box"); consloe.log(box.style.width);// 打印的是空字符串,因為只能獲取行內樣式 box.style.width = "300px";// 設置的是行內樣式,而且這裏必須帶單位 console.log(box.style.width);// 打印的是“300px“/
2、通過類名設置樣式
.b{ width:100px; height:100px; background-color:red; } <div id="box"></div> var box = document.getElementById("box"); // 通過類名設置樣式 兩種方式 box.className = "b"; box.setAttribute("class","b");
下面介紹事件綁定
綁定事件
事件三要素: 事件源 事件 事件處理程序
事件源.事件 = function(){ // 事件處理程序 } <img src="pic.jpg" id="img"/> var img = document.getElementById("img"); img.onclick = function(){ ... }
img是事件源 事件是點擊onclick 事件處理程序是函數體中的內容
下面為常用事件總結
屬性 |
描述 |
Onblur |
元素失去焦點。 |
Onchange |
域的內容被改變。 |
Onclick |
當用戶點擊某個對象時調用的事件句柄。 |
ondblclick |
當用戶雙擊某個對象時調用的事件句柄。 |
Onfocus |
元素獲得焦點。 |
onkeydown |
某個鍵盤按鍵被按下。 |
onkeypress |
某個鍵盤按鍵被按下並松開。 |
Onkeyup |
某個鍵盤按鍵被松開。 |
Onload |
一張頁面或一幅圖像完成加載。 |
onmousedown |
鼠標按鈕被按下。 |
onmousemove |
鼠標被移動。 |
onmouseout |
鼠標從某元素移開。 |
onmouseover |
鼠標移到某元素之上。 |
onmouseup |
鼠標按鍵被松開。 |
Onreset |
重置按鈕被點擊。 |
Onresize |
窗口或框架被重新調整大小。 |
Onunload |
用戶退出頁面。 |
節點操作
節點操作就5種形式,克隆節點、添加節點、插入節點、移除節點和創建節點。
克隆節點 - cloneNode()
element.cloneNode(): 復制element節點
參數:布爾值,
true代表深層克隆,把當前節點和內部所有節點都復制一份
false代表淺層克隆,只復制當前節點
<div id="father"> <div id="son"><div/> </div> var father = document.getElementById("father"); var son = document.getElementById("son"); var clone = son.cloneNode(true);// 把son這個div復制一份 復制出來的clone和son沒有任何關系了
添加節點 - appendChild()
father.appendChild(son):將son節點追加到father內部的最後位置
<div id="father"> <div id="son"><div/> </div> <div id="demo"></div> var father = document.getElementById("father"); var demo = document.getElementById("demo"); var clone = demo.cloneNode(true);// 將demo克隆一份 father.appendChild(clone);// 將克隆出來的clone追加到father中 // 此時頁面結構應該為 <div id="father"> <div id="son"><div/> <div id="demo"></div> </div> <div id="demo"></div>
//追加克隆節點對原節點不會產生影響
//如果代碼如下 則會將demo節點直接移動到father節點下
father.appendChild(demo);// demo是頁面上存在的節點
// 此時頁面結構應該為
<div id="father">
<div id="son"><div/>
<div id="demo"></div>
</div>
插入節點 - insertBefore()
father.inserBefore(son1,son2): 將son1插入到father節點下的son2前面
<div id="father"> <div id="son"><div/> </div> <div id="demo"></div> var father = document.getElementById("father"); var son = document.getElementById("son"); var demo = document.getElementById("demo"); father.inserBefore(son,demo);//會直接將demo節點移動到father下的son前面
插入克隆出來的節點也不會對原節點產生影響
移除節點 - removeChild()
father.removeChild(son): 將father下的son節點移除
<div id="father"> <div id="son"><div/> </div> var father = document.getElementById("father"); var son = document.getElementById("son"); father.removeChild(son);// 直接將son節點刪除
創建節點
document.write()
特點:只能被document調用,而且會覆蓋頁面上原有內容
document.write("<a href="http://www.baidu.com">百度</a>")
// 可以在頁面上創建一個a標簽,而且會覆蓋頁面上原有的所有內容
innerHtml()
特點:往頁面添加html標簽,可以限定範圍
<div id="box"></div> var box = document.getElementById("box"); box.innerHtml = "<a href="http://www.baidu.com">百度</a>"; // 追加後的結構為 <div id="box"> <a href="http://www.baidu.com">百度</a> </div>
createElement()
特點:動態創建標簽,添加到頁面需要配合appendChild使用。
<div id="box"></div> var box = document.getElementById("box"); var input = document.createElement("input"); input.type = "text"; box.appendChild(input);
DOM的基本操作就到此為止了,如果對你有所幫助就給本文點個贊吧O(∩_∩)O
一篇文章搞懂DOM