1. 初識DOM 1.1 DOM介紹 1.1.3 什麼是DOM DOM:文檔對象模型。DOM 為文檔提供了結構化表示,並定義瞭如何通過腳本來訪問文檔結構。目的其實就是為了能讓js操作html元素而制定的一個規範。 DOM就是由節點組成的。 1.1.2 解析過程 HTML載入完畢,渲染引擎會在記憶體中把 ...
1. 初識DOM
1.1 DOM介紹
1.1.3 什麼是DOM
DOM:文檔對象模型。DOM 為文檔提供了結構化表示,並定義瞭如何通過腳本來訪問文檔結構。目的其實就是為了能讓js操作html元素而制定的一個規範。
DOM就是由節點組成的。
1.1.2 解析過程
HTML載入完畢,渲染引擎會在記憶體中把HTML文檔,生成一個DOM樹,getElementById是獲取內中DOM上的元素節點。然後操作的時候修改的是該元素的屬性。
1.1.3 DOM樹(一切都是節點)
DOM的數據結構如下:
上圖可知,在HTML當中,一切都是節點:
元素節點:HMTL標簽。
文本節點:標簽中的文字(比如標簽之間的空格、換行)。
屬性節點:標簽的屬性。
整個html文檔就是一個文檔節點。所有的節點都是Object。
1.1.4 DOM可以做什麼
找對象(元素節點)
設置元素的屬性值
設置元素的樣式
動態創建和刪除元素
事件的觸發響應:事件源、事件、事件的驅動程式
1.2 DOM節點的獲取
DOM節點的獲取方式其實就是獲取事件源的方式
操作元素節點,必須首先找到該節點。有三種方式可以獲取DOM節點:
var div1 = document.getElementById("box1"); //方式一:通過id獲取單個標簽 var arr1 = document.getElementsByTagName("div1"); //方式二:通過 標簽名 獲得 標簽數組,所以有s var arr2 = document.getElementsByClassName("hehe"); //方式三:通過 類名 獲得 標簽數組,所以有s
既然方式二、方式三獲取的是標簽數組,那麼習慣性是先遍歷之後再使用。
特殊情況:數組中的值只有1個。即便如此,這一個值也是包在數組裡的。這個值的獲取方式如下:
document.getElementsByTagName("div1")[0]; //取數組中的第一個元素 document.getElementsByClassName("hehe")[0]; //取數組中的第一個元素
1.3 DOM訪問關係的獲取
DOM的節點並不是孤立的,因此可以通過DOM節點之間的相對關係對它們進行訪問。如下:
節點的訪問關係,是以屬性的方式存在的。
JS中的父子兄訪問關係:
這裡我們要重點知道parentNode和children這兩個屬性的用法。下麵分別介紹。
1.3.1 獲取父節點
調用者就是節點。一個節點只有一個父節點,調用方式就是:
節點.parentNode
(1) nextSibling
指的是下一個節點(包括標簽、空文檔和換行節點)
火狐、谷歌、IE9+版本:都指的是下一個節點(包括標簽、空文檔和換行節點)。
IE678版本:指下一個元素節點(標簽)。
(2) nextElementSibling
火狐、谷歌、IE9+版本:都指的是下一個元素節點(標簽)。
總結:為了獲取下一個元素節點,我們可以這樣做:在IE678中用nextSibling,在火狐谷歌IE9+以後用nextElementSibling,於是,綜合這兩個屬性,可以這樣寫:
下一個兄弟節點 = 節點.nextElementSibling || 節點.nextSibling
previous的中文是: 前一個
(1) previousSibling
火狐、谷歌、IE9+版本:都指的是前一個節點(包括標簽、空文檔和換行節點)。
IE678版本:指前一個元素節點(標簽)。
(2) previousElementSibling
火狐、谷歌、IE9+版本:都指的是前一個元素節點(標簽)。
總結:為了獲取前一個元素節點,我們可以這樣做:在IE678中用previousSibling,在火狐谷歌IE9+以後用previousElementSibling,於是,綜合這兩個屬性,可以這樣寫:
前一個兄弟節點 = 節點.previousElementSibling || 節點.previousSibling
獲得任意一個兄弟節點:
節點自己.parentNode.children[index]; //隨意得到兄弟節點
1.3.2 獲取單個的子節點
(1) 第一個子節點 | 第一個子元素節點
1.firstChild:
火狐、谷歌、IE9+版本:都指的是第一個子節點(包括標簽、空文檔和換行節點)。
IE678版本:指第一個子元素節點(標簽)。
2.firstElementChild
火狐、谷歌、IE9+版本:都指的是第一個子元素節點(標簽)。
總結:為了獲取第一個子元素節點,我們可以這樣做:在IE678中用firstChild,在火狐谷歌IE9+以後用firstElementChild,於是,綜合這兩個屬性,可以這樣寫:
第一個子元素節點 = 節點.firstElementChild || 節點.firstChild
(2) 最後一個子節點 | 最後一個子元素節點
1.lastChild
火狐、谷歌、IE9+版本:都指的是最後一個子節點(包括標簽、空文檔和換行節點)。
IE678版本:指最後一個子元素節點(標簽)。
2.lastElementChild
火狐、谷歌、IE9+版本:都指的是最後一個子元素節點(標簽)。
總結:為了獲取最後一個子元素節點,我們可以這樣做:在IE678中用lastChild,在火狐谷歌IE9+以後用lastElementChild,於是,綜合這兩個屬性,可以這樣寫:
最後一個子元素節點 = 節點.lastElementChild || 節點.lastChild
1.3.3 獲取所有的子節點
1.childNodes:標準屬性。返回的是指定元素的子節點的集合(包括元素節點、所有屬性、文本節點)。是W3C的親兒子。
火狐、谷歌等高本版會把換行也看做是子節點。
用法:
子節點數組 = 父節點.childNodes; //獲取所有節點。
2.children:非標準屬性。返回的是指定元素的子元素節點的集合。
它只返回HTML節點,甚至不返迴文本節點。
在IE6/7/8中包含註釋節點(在IE678中,註釋節點不要寫在裡面)。
雖然不是標準的DOM屬性,但它和innerHTML方法一樣,得到了幾乎所有瀏覽器的支持。
用法:
子節點數組 = 父節點.children; //獲取所有節點。用的最多。
1.4 DOM節點操作
上一段的內容:節點的訪問關係都是屬性。
節點的操作都是函數(方法)
1.4.1 創建節點
格式如下:
新的標簽(元素節點) = document.createElement("標簽名");
比如,如果我們想創建一個li標簽,或者是創建一個不存在的adbc標簽,可以這樣做:
<script type="text/javascript"> var a1 = document.createElement("li"); //創建一個li標簽 var a2 = document.createElement("adbc"); //創建一個不存在的標簽 console.log(a1); console.log(a2); console.log(typeof a1); console.log(typeof a2); </script>
結果:
1.4.2 插入節點
插入節點有兩種方式,它們的含義是不同的。
方式1:
父節點.appendChild(新的子節點);
解釋:父節點的最後插入一個新的子節點。
方式2:
父節點.insertBefore(新的子節點,作為參考的子節點);
解釋:
在參考節點前插入一個新的節點。
如果參考節點為null,那麼他將在父節點最後插入一個子節點。
1.4.3 刪除節點
格式如下:
父節點.removeChild(子節點);
解釋:用父節點刪除子節點。必須要指定是刪除哪個子節點。
如果我想刪除自己這個節點,可以這麼做:
node1.parentNode.removeChild(node1);
1.4.4 複製節點
格式如下:
要複製的節點.cloneNode(); //括弧里不帶參數和帶參數false,效果是一樣的。 要複製的節點.cloneNode(true);
括弧裡帶不帶參數,效果是不同的。解釋如下:
不帶參數/帶參數false:只複製節點本身,不複製子節點。
帶參數true:既複製節點本身,也複製其所有的子節點。
1.5 設置節點的屬性
我們可以獲取節點的屬性值、設置節點的屬性值、刪除節點的屬性。
我們就統一拿下麵這個標簽來舉例:
<img src="images/1.jpg" class="image-box" title="美女圖片" alt="地鐵一瞥" id="a1">
下麵分別介紹。
1.5.1 獲取節點的屬性值
方式1:
元素節點.屬性;
元素節點[屬性];
舉例:(獲取節點的屬性值)
<body> <img src="images/1.jpg" class="image-box" title="美女圖片" alt="地鐵一瞥" id="a1"> <script type="text/javascript"> var myNode = document.getElementsByTagName("img")[0]; console.log(myNode.src); console.log(myNode.className); //註意,是className,不是class console.log(myNode.title); console.log("------------"); console.log(myNode["src"]); console.log(myNode["className"]); //註意,是className,不是class console.log(myNode["title"]); </script> </body>
方式2:
素節點.getAttribute("屬性名稱");
例子:
console.log(myNode.getAttribute("src")); console.log(myNode.getAttribute("class")); //註意是class,不是className console.log(myNode.getAttribute("title"));
方式1和方式2的區別在於:前者是直接操作標簽,後者是把標簽作為DOM節點。推薦方式2。
1.5.2 設置節點的屬性值
方式1舉例:(設置節點的屬性值)
myNode.src = "images/2.jpg" //修改src的屬性值 myNode.className = "image2-box"; //修改class的name
方式2:
元素節點.setAttribute(屬性名, 新的屬性值);
例子:
myNode.setAttribute("src","images/3.jpg"); myNode.setAttribute("class","image3-box"); myNode.setAttribute("id","你好");
1.5.3 刪除節點的屬性
格式:
元素節點.removeAttribute(屬性名);
例子:
myNode.removeAttribute("class");
myNode.removeAttribute("id");