文檔對象模型 (DOM) 是HTML和XML文檔的編程接口。它給文檔(結構樹)提供了一個結構化的表述而且定義了一種方式—程序能夠對結構樹進行訪問,以改變文檔的結構,樣式和內容。html
DOM 提供了一種表述形式將文檔做爲一個結構化的節點組以及包含屬性和方法的對象。從本質上說,它將web 頁面和腳本或編程語言鏈接起來了。node
要改變頁面的某個東西,JavaScript就須要得到對HTML文檔中全部元素進行訪問的入口。這個入口,連同對 HTML 元素進行添加、移動、改變或移除的方法和屬性,都是經過DOM來得到的web
每一個載入瀏覽器的HTML文檔都會成爲document對象。document對象包含了文檔的基本信息,咱們能夠經過JavaScript對HTML頁面中的全部元素進行訪問、修改。編程
document對象有不少屬性來描述文檔信息,介紹幾個經常使用的數組
document.doctype
document.title
document.characterSet
document.head
document.body
document.images
/*瞭解
readyState屬性返回當前文檔的狀態,共有三種可能的值
1. loading:加載HTML代碼階段,還沒有完成解析
2. interactive:加載外部資源階段
3. complete:所有加載完成
*/
document.readyState
/*瞭解
compatMode 屬性返回瀏覽器處理文檔的模式,可能的值爲
1. BackCompat:向後兼容模式,也就是沒有添加DOCTYPE
2. CSS1Compat:嚴格模式,添加了DOCTYPE
*/
document.compatMode
複製代碼
document.location 也可直接使用 location瀏覽器
document.location === location //true
document.location === window.location //true
複製代碼
location屬性返回一個只讀對象,提供了當前文檔的URL信息緩存
// 假定當前網址爲http://user:passwd@www.example.com:4097/path/a.html?x=111#part1
document.location.href // "http://user:passwd@www.example.com:4097/path/a.html?x=111#part1"
document.location.protocol // "http:"
document.location.host // "www.example.com:4097"
document.location.hostname // "www.example.com"
document.location.port // "4097"
document.location.pathname // "/path/a.html"
document.location.search // "?x=111"
document.location.hash // "#part1"
document.location.user // "user"
document.location.password // "passed"
// 跳轉到另外一個網址
document.location.assign('http://www.google.com')
// 優先從服務器從新加載
document.location.reload(true)
// 優先從本地緩存從新加載(默認值)
document.location.reload(false)
// 跳轉到另外一個網址,但當前文檔不保留在history對象中,
// 即沒法用後退按鈕,回到當前文檔
document.location.assign('http://www.google.com')
// 將location對象轉爲字符串,等價於document.location.href
document.location.toString()
複製代碼
雖然location屬性返回的對象是隻讀的,可是能夠將URL賦值給這個屬性,網頁就會自動跳轉到指定網址。bash
document.location = 'http://www.example.com';
// 等價於
document.location.href = 'http://www.example.com';
複製代碼
document.open方法用於新建一個文檔,供write方法寫入內容。它實際上等於清除當前文檔,從新寫入內容服務器
document.close方法用於關閉open方法所新建的文檔。一旦關閉,write方法就沒法寫入內容了。數據結構
document.write方法用於向當前文檔寫入內容。只要當前文檔尚未用close方法關閉,它所寫入的內容就會追加在已有內容的後面。
document.open();
document.write("hello");
document.write("world");
document.close();
複製代碼
1.若是頁面已經渲染完成再調用write方法,它會先調用open方法,擦除當前文檔全部內容,而後再寫入。
2.若是在頁面渲染過程當中調用write方法,並不會調用open方法。
須要注意的是,雖然調用close方法以後,沒法再用write方法寫入內容,但這時當前頁面的其餘DOM節點仍是會繼續加載。
除了某些特殊狀況,應該儘可能避免使用document.write這個方法。
Element 對象能夠擁有類型爲元素節點、文本節點、註釋節點的子節點,DOM提供了一系列的方法能夠進行元素的增、刪、改、查操做
Element有幾個重要屬性
1.nodeName:元素標籤名,還有個相似的tagName
2.nodeType:元素類型
3.className:類名
4 .id:元素id
5.children:子元素列表(HTMLCollection)
6.childNodes:子元素列表(NodeList)
7.firstChild:第一個子元素
8.lastChild:最後一個子元素
9.nextSibling:下一個兄弟元素
10.previousSibling:上一個兄弟元素
11.parentNode、parentElement:父元素
getElementById方法返回匹配指定ID屬性的元素節點。若是沒有發現匹配的節點,則返回null。這也是獲取一個元素最快的方法
var elem = document.getElementById("test");
getElementsByClassName方法返回一個相似數組的對象(HTMLCollection類型的對象),包括了全部class名字符合指定條件的元素(搜索範圍包括自己),元素的變化實時反映在返回結果中。這個方法不只能夠在document對象上調用,也能夠在任何元素節點上調用。
var elements = document.getElementsByClassName('tab');
getElementsByClassName方法的參數,能夠是多個空格分隔的class名字,返回同時具備這些節點的元素。
document.getElementsByClassName('red test');
複製代碼
getElementsByTagName方法返回全部指定標籤的元素(搜索範圍包括自己)。返回值是一個HTMLCollection對象,也就是說,搜索結果是一個動態集合,任何元素的變化都會實時反映在返回的集合中。這個方法不只能夠在document對象上調用,也能夠在任何元素節點上調用。
var paras = document.getElementsByTagName("p");
複製代碼
上面代碼返回當前文檔的全部p元素節點。注意,getElementsByTagName方法會將參數轉爲小寫後,再進行搜索。
// 假定有一個表單是<form name="x"></form>
var forms = document.getElementsByName("x");
forms[0].tagName // "FORM"
複製代碼
注意,在IE瀏覽器使用這個方法,會將沒有name屬性、但有同名id屬性的元素也返回,因此name和id屬性最好設爲不同的值。
querySelector方法返回匹配指定的CSS選擇器的元素節點。若是有多個節點知足匹配條件,則返回第一個匹配的節點。若是沒有發現匹配的節點,則返回null。
var el1 = document.querySelector(".myclass");
var el2 = document.querySelector('#myParent > [ng-click]');
複製代碼
querySelector方法沒法選中CSS僞元素。
querySelectorAll方法返回匹配指定的CSS選擇器的全部節點,返回的是NodeList類型的對象。NodeList對象不是動態集合,因此元素節點的變化沒法實時反映在返回結果中。
elementList = document.querySelectorAll(selectors);
querySelectorAll方法的參數,能夠是逗號分隔的多個CSS選擇器,返回全部匹配其中一個選擇器的元素。
var matches = document.querySelectorAll("div.note, div.alert");
上面代碼返回class屬性是note或alert的div元素。
createElement方法用來生成HTML元素節點。
var newDiv = document.createElement("div");
createElement方法的參數爲元素的標籤名,即元素節點的tagName屬性。若是傳入大寫的標籤名,會被轉爲小寫。若是參數帶有尖括號(即<和>)或者是null,會報錯。
createTextNode方法用來生成文本節點,參數爲所要生成的文本節點的內容。
var newDiv = document.createElement("div");
var newContent = document.createTextNode("Hello");
複製代碼
上面代碼新建一個div節點和一個文本節點
createDocumentFragment方法生成一個DocumentFragment對象。
var docFragment = document.createDocumentFragment();
DocumentFragment對象是一個存在於內存的DOM片斷,可是不屬於當前文檔,經常用來生成較複雜的DOM結構,而後插入當前文檔。這樣作的好處在於,由於DocumentFragment不屬於當前文檔,對它的任何改動,都不會引起網頁的從新渲染,比直接修改當前文檔的DOM有更好的性能表現。
fragment至關於生成了一個虛擬的標籤,將其餘的元素放進去以後,將fragment放入頁面中時,fragment就消失了。若是不用fragment就須要額外的添加標籤做爲容器去容納其餘元素。
在元素末尾添加元素
var newDiv = document.createElement("div");
var newContent = document.createTextNode("Hello");
newDiv.appendChild(newContent);
複製代碼
在某個元素以前插入元素
var newDiv = document.createElement("div");
var newContent = document.createTextNode("Hello");
newDiv.insertBefore(newContent, newDiv.firstChild);
複製代碼
replaceChild()接受兩個參數:要插入的元素和要替換的元素
newDiv.replaceChild(newElement, oldElement);
刪除元素使用removeChild()方法便可
parentNode.removeChild(childNode);
複製代碼
cloneNode()方法用於克隆元素,方法有一個布爾值參數,傳入true的時候會深複製,也就是會複製元素及其子元素(IE還會複製其事件),false的時候只複製元素自己
node.cloneNode(true);
複製代碼
getAttribute()用於獲取元素的attribute值
node.getAttribute('id');
createAttribute()方法生成一個新的屬性對象節點,並返回它。
attribute = document.createAttribute(name);
createAttribute方法的參數name,是屬性的名稱。
setAttribute()方法用於設置元素屬性
var node = document.getElementById("div1");
node.setAttribute("my_attrib", "newVal");
複製代碼
等同於
var node = document.getElementById("div1");
var a = document.createAttribute("my_attrib");
a.value = "newVal";
node.setAttributeNode(a);
複製代碼
removeAttribute()用於刪除元素屬性
node.removeAttribute('id');
複製代碼
固然上面的方法作的事情也能夠經過類操做數組屬性element.attributes來實現
innerText是一個可寫屬性,返回元素內包含的文本內容,在多層次的時候會按照元素由淺到深的順序拼接其內容
<div>
<p>
123
<span>456</span>
</p>
</div>
複製代碼
外層div的innerText返回內容是 "123456"
innerHTML屬性做用和innerText相似,可是不是返回元素的文本內容,而是返回元素的HTML結構,在寫入的時候也會自動構建DOM
<div>
<p>
123
<span>456</span>
</p>
</div>
複製代碼
外層div的innerHTML返回內容是"<p>123<span>456</span></p>"
可修改元素的 style 屬性,修改結果直接反映到頁面元素
document.querySelector('p').style.color = 'red'
document.querySelector('.box').style.backgroundColor = '#ccc'
複製代碼
使用getComputedStyle獲取元素計算後的樣式,不要經過 node.style.屬性 獲取
var node = document.querySelector('p')
var color = window.getComputedStyle(node).color
console.log(color)
複製代碼
var nodeBox = document.querySelector('.box')
console.log( nodeBox.classList )
nodeBox.classList.add('active') //新增 class
nodeBox.classList.remove('active') //刪除 class
nodeBox.classList.toggle('active') //新增/刪除切換
node.classList.contains('active') // 判斷是否擁有 class
複製代碼
樣式的改變儘可能使用 class 的新增刪除來實現
element.clientHeight
element.offsetHeight
document.body.clientHeight
document.body.offsetHeight
docuemnt.body.style.border = "10px solid red"
docuemnt.body.clientHeight //變小了
document.body.offsetHeight
複製代碼
元素內容的總長度(包括滾動的)。若是元素沒出現滾動條, scrollHeight等於 clientHeight
document.body.scrollHeight
複製代碼
document.body.scrollTop
複製代碼
window.innerHeigh
複製代碼
問題1: 若是判斷一個元素距離 document 頂部的偏移
function getOffsetTop( elem ){
var offsetLeft = 0
do {
offsetTop += elem.offsetTop
} while( elem = elem.offsetParent )
return offsetTop
}
或者
element.getBoundingClientRect().top + document.body.scrollTop
複製代碼
問題2:如何判斷一個元素是否出如今窗口視野中
問題3:若是判斷頁面滾動到底部
節點都是單個對象,有時會須要一種數據結構,可以容納多個節點。DOM提供兩種集合對象,用於實現這種節點的集合:NodeList和HTMLCollection。
NodeList 對象表明一個有順序的節點列表,HTMLCollection 是一個接口,表示 HTML 元素的集合,它提供了能夠遍歷列表的方法和屬性
如下方法獲取的爲HTMLCollection對象
document.images //全部img元素
document.links //全部帶href屬性的a元素和area元素
document.forms //全部form元素
document.scripts //全部script元素
document.body.children
document.getElementsByClassName("class1")
複製代碼
如下方法獲取的爲NodeList對象
document.getElementsByName("name1")
document.getElementsByTagName("a")
document.querySelectorAll("a")
document.body.childNodes
複製代碼
如何查看?
document.body.childNodes.constructor
複製代碼
HTMLCollection與NodeList基本類似
相同點: 都是類數組對象,節點的變化都會實時反映在集合中
不一樣點: 少部分方法不同,好比 NodeList 有 forEach 方法,而 HTMLCollection 沒有