18.DOM進階

DOM進階html

學習要點:
1.DOM類型
2.DOM擴展
3.DOM操做內容node

DOM自身存在不少類型,在DOM基礎課程中大部分都有所接觸,好比Element類型,表示的是元素節點,再好比
Text類型:表示的是文本節點。DOM也提供了一些擴展功能。c++

1、DOM類型
DOM基礎課程中,咱們瞭解了DOM的節點而且瞭解怎麼查詢和操做節點,而自己這些不一樣的節點,又有着不一樣的
類型。瀏覽器

DOM 類型
類型名 說明
Node 表示全部類型值的統一接口,IE不支持
Document 表示文檔類型
Element 表示元素節點類型
Text 表示文本節點
Comment 表示文檔中的註釋類型
CDATASection 表示CDATA區域類型
DocumentType 表示文檔聲明
DocumentFragment 表示文檔片斷類型
Attr 表示屬性節點類型服務器

 

1.Node類型
Node接口是DOM1級就定義了,Node接口定義了12個數值常量以表示每一個節點的類型值,除了IE以外,全部
瀏覽器均可以訪問這個類型。app

Node的常量
常量名 說明 nodeType值
ELEMENT_NODE 元素 1
ATTRIBUTE_NODE 屬性 2
TEXT_NODE 文本 3
CDATA_SECTION_NODE CDATA 4
ENTITY_REFERENCE_NODE 實體參考 5
ENTITY_NODE 實體 6
PROCESSING_INSIRUCETION_NODE 處理指令 7
COMMENT_NODE 註釋 8
DOCUMENT_NODE 文檔根 9
DOCUMENT_TYPE_NODE doctype 10
DOCUMENT_FRAGMENT_NODE 文檔片斷 11
NOTATION_NODE 符號 12dom

雖然這裏介紹了12種節點對象的屬性,用的多的其實也就幾個而已。
alert(Node.ELEMENT_NODE); //1.元素節點類型值
alert(Node.TEXT_NODE); //2.文本節點類型值函數

咱們建議使用Node類型的屬性來代替1,2這些阿拉伯數字,有可能你們會以爲這樣豈不是很繁瑣嗎?而且還有一個
問題就是IE不支持Node類型。性能

若是隻有兩個屬性的話,用1,2來代替會特別方便,但若是屬性特別多的狀況下,1,2,3,4,5,6,7,8,9,10,11,12,
你根本就分不清那個數字表明的是哪一個節點,固然,若是你只用1,2兩個節點,那就另當別論了。學習

IE不支持,咱們能夠模擬一個類,讓IE也支持。
if(typeof Node == 'undefined'){ //IE返回
window.Node ={
ELEMENT_NODE : 1,
TEXT_NODE : 3
};
}

2.Document類型
Document類型表示文檔,或文檔的根節點,而這個節點時隱藏的,沒有具體的元素標籤。
document; //document
document.nodeType; //9,類型值
document.childNodes[0]; //DocumentType,第一個子節點對象,IE理解爲註釋
document.childNodes[0].nodeType; //非IE爲10,IE爲8
document.childNodes[0].nodeName; //火狐爲HTML,谷歌爲html,IE爲#comment
document.childNodes[1]; //HTML.HtmlElement
document.childNodes[1].nodeType; //HTML

若是想直接獲得<html>標籤的元素節點對象HTML.HtmlElement,沒必要使用childNodes屬性這麼麻煩,可使
用documentElement便可。

document.documentElement; //HTML.HtmlElement

在不少狀況下,咱們並不須要獲得<html>標籤的元素節點,而須要獲得更經常使用的<body>標籤,以前咱們採用的
是:document.getElementsByTagName('body')[0],,那麼這裏提供了一個更簡便的方法:document.body

document.body; //HTML.BodyElement

在<html>以前還有一個文檔聲明;<!DOCTYPE>會做爲某些瀏覽器的第一個節點來處理,這裏提供一個簡便
方法來處理:document.dctype。
document.doctype; //DocumentType

PS:IE8中,若是使用子節點訪問,IE8以前會解釋爲讓註釋類型Comment節點,而document.doctyoe則會返回
null。
document.childNodes[0].nodeName //IE會是#Comment

在Document中有一些遺留的屬性和對象合集,可使用的幫助咱們精確的處理一些任務。


//屬性
document.title; //獲取和設置<title>標籤的值
document.URL; //獲取URL路徑
document.domain; //獲取域名,服務器端
document.referrer; //獲取上一個URL,服務器端


//對象合集
document.anchors; //獲取文檔中帶name屬性的<a>元素集合
document.links; //獲取文檔中帶href屬性的<a>元素集合
document.applets; //獲取文檔中<applet>元素集合,已不用
document.forms; //獲取文檔中<form>元素集合
document.images; //獲取文檔中<img>元素集合

3.Element類型
Element類型用於表現HTML中的元素節點,在DOM基礎那章,咱們已經能夠對元素節點進行查找、建立等操做
元素節點的nodeType爲1,nodeName爲元素的標籤名。
元素節點對象在IE瀏覽器能夠返回它具體元素節點的對象類型。

元素對應類型表

元素名 類型
HTML HTML.HtmlElement
DIV HTML.DivElement
BODY HTML.BodyElement
p HTML.ParamElement

PS:以上給出了部分對應,更多的元素對應類型,直接訪問調用便可。

 

4.Text類型
Text類型用於表現文本節點類型,文本不包含HTML,或包含轉義後的HTML。文本節點的nodeType爲3。
在同時建立兩個同一級別的文本節點的時候,會產生分離的兩個節點。
var box = document.createElement('div');
var text = document.createTextNode('Mr');
var text2 = document.createTextNode('Lee');
box.appendChild(text);
box.appendChild(text2);
document.body.appendChild(box);
alert(box.childNodes.length); //2,兩個文本節點


PS:把兩個文本節點合併在一塊兒使用normalize()便可
box.normalize(); //合併成一個節點

PS:有合併就有分離,經過splitText(num)便可實現節點分離。
box.firstChild.splitText(3); //分離一個節點,把前三個分離成新節點

除了上面的兩種方法外,Text還提供了一些別的DOM操做的方法以下:
var box = document.getElementById('box');

box.firstChild.deleteData(0,2); //刪除從0位置的2個字符
box.firstChild.insertData(0,'Hello'); //從0位置添加指定字符
box.firstChild.replaceData(0,2,'Miss'); //從0位置替換掉2個指定字符
box.firstChild.substringData(0,2); //從0位置獲取2個字符,直接輸出
alert(box.firstChild.nodeValue); //輸出結果

 

5.Comment類型
Comment類型表示文檔中的註釋,nodeType是8,nodeName是#Comment,nodeValue是註釋的內容。

var box = document.getElementById('box');
alert(box.firstChild); //Comment

PS:在IE中,註釋節點可使用!號看成元素來訪問。
var comment = document.getElementsByTagName('!');
alert(comment.length);


6.Attr類型
Attr類型表示文元素中的屬性。nodeType爲2,nodeName爲屬性名,nodeValue爲屬性值,DOM基礎已經
詳細介紹。

 

 


2、DOM擴展
1.呈現模式
從IE6開始區分標準模式和混雜模式(怪異模式),主要是看文檔的聲明。IE爲document對象添加一個名爲
compatMode屬性。這個屬性能夠識別IE瀏覽器的文檔處於什麼模式,若是是標準模式,則返回CSS1Compat
,若是時混雜模式則返回BackCompat。
if(document.compatMode == 'CSS1Compat'){
alert(document.documentElement.clientWidth);
}else{
alert(document.body.clientWidth);
}

PS:後來Firefox、Opera和Chome都實現了這個屬性。從IE8後,又引入了documentMode新屬性,由於IE8
有3種呈現模式分別爲標準模式8,仿真模式7,混雜模式5。因此若是想測試IE8的標準模式,就判斷
document.documentMode > 7便可。

2.滾動
DOM提供了一些滾動頁面的方法,以下:
document.getElementById('box').scrollIntoView(); //設置指定可見,將指定的節點滾動到可見範圍


3.children屬性
因爲子節點空白問題,IE和其餘瀏覽器解釋不一致。雖然能夠過濾掉,但若是隻是想獲得有效子節點,可使用
children屬性,支持的瀏覽器爲:IE5+、Firefox3.5+、Safari2+、Opera8+和Chrome,這個屬性是非標準的。
var box = document.getElementById('box');
alert(box.children.length); //獲得有效子節點數目,忽略掉了空白節點

 

4.contains()方法
判斷一個節點是否是另外一個節點的後代,咱們可使用contains()方法,這個方法是IE率先使用的,開發人員無須
遍歷便可獲取此信息。
var box = document.getElementById('box');
alert(box.contains(box.firstChild)); //true

PS:早期的Firefox不支持這個方法,新版的支持了,其餘瀏覽器也都支持,Safari瀏覽器支持的有問題,沒法使
用,因此,必須作兼容。

function contains(refNode , otherNode){
if(typeof refNode.contains != 'undefined'){
return refNode.contains(otherNode);
}else if(typeof refNode.compareDocumentPosition == 'function'){
return refNode.compareDocumentPosition(otherNode) > 16;
}
}

 

在Firefox的DOM3級實現中提供了一個替代的方法compareDocumentPosition()方法。
這個方法肯定兩個節點之間的關係。

var box = document.getElementById('box');
alert(box.compareDocumentPosition(box.firstChild)); //20,大於16就是包含關係

關係掩碼錶
掩碼 節點關係
1 無關(節點不存在)
2 居前(節點在參考點以前)
4 居後(節點在參考點以後)
8 包含(節點是參考點的祖先)
16 被包含(節點時參考點的後代)

PS:爲何會出現20,那是由於知足了4和16兩項,最後相加了。爲了能讓全部瀏覽器均可以兼容,咱們必須
寫一個兼容性的函數。

 

//傳遞參考節點(父節點),和其餘節點(子節點)
function contains(refNode , otherNode){
//判斷支持comtains,而且非Safari瀏覽器
if(typeof refNode.contains != 'undefined' && !(BrowserDetect.browser == 'Safari' && BrowserDetect.version < 3)){
return refNode.comment(otherNode);
//判斷支持compareDocumentPosition的瀏覽器,大於16就是包含
}else if(typeof refNode.compareDocumentPosition == 'function'){
return !!(refNode.compareDocumentPosition(otherNode) > 16);
}else{
//更低的瀏覽器兼容,經過遞歸一個個獲取他的父節點是否存在
var node = otherNode.parentNode;
do{
if(node == refNode){
return true;
}else{
node = node.parentNode;
}
}while (node != null);
}
return false;
}

 


3、DOM操做內容
雖然在以前咱們已經學習了各類DOM操做的方法,這裏所介紹是innerText、innerHTML、otherText和otherHTML
等屬性。除了以前用過的innerHTML以外。其餘三個尚未涉及到。

1.innerText屬性
document.getElementById('box').innerText; //獲取文本內容(若有html直接過濾掉)
document.getElementById('box').innerText='Mr.Lee';//設置文本(若有html轉義)


PS:除了Firefix以外,其餘瀏覽器均支持這個方法。但Firefox的DOM3級提供了另一個相似的屬性:
textCotent,作上兼容可通用。

document.getElementById('box').textContent; //Firefox支持

//兼容方案
function getInnerText(element){
return(typeof element.textContent == 'string')?element.textContent : element.innerText;
}
function setInnerText(element.text){
if(typeof.element.textContent == 'string'){
element.textContent = text;
}else{
element.innerText = text;
}
}

 

2.innerHTML屬性
這個屬性以前就已經研究過,不拒絕HTML。
document.getElementById('box').innerTHML; //獲取文本(不過濾HTML)
document.getElementById('box').innerHTML = '<b>123</b>'; //可解析HTML

雖然innerHTML可插入HTML,但自己仍是有必定的限制,也就是所謂的做用域元素,離開這個做用域就無效了。
box.innerHTML = "<script>alert('Lee')</script>"; //<script>元素不能執行
box.innerHTML = "<style>background:red;</style>"; //<style>元素不能被執行

3.outerText
outerText在取值的時候和innerHTML同樣,同時火狐不支持,而賦值方法至關危險,它不單替換了文本內容,
還將元素直接抹去。

var box = document.getElementById('box');
box.outerText = '<b>123</b>';
alert(document.getElementById('box')); //null,建議不去使用


4.outerHTML
outerHTML屬性在取值和innerHTML一致,但和outerText也同樣,很危險,賦值的以後將元素抹去。
var box = document.getElementById('box');
box.outerHTML = '123';
alert(document.getElementById('box')); //null,建議不去使用

PS:關於最經常使用的innerHTML屬性和節點操做方法的比較,在插入大量HTML標記時使用innerHTML的效率明顯
要高不少,由於在設置innerHTML時,會建立一個HTML解析器,這個解析器是瀏覽器級別的(c++編寫的),
所以執行Javascript會快的多。但建立和銷燬HTML解析器也會帶來性能損失。最好控制在最合理的範圍內,以下:
for(var i = o ; i<10 ; i++){
ul.innerHTML = '<li>inem<li>'; //避免頻繁
}
//改
for(var i = 0 ; i<10; i++){
a = '<li>item<li>'; //臨時保存
}
ul.innerHTML = a;


HTML5中新API:
按類名查找元素:IE8不支持
var elems=
document/parentNode.getElementsByClassName("類名")

按選擇器查找元素:IE8支持!
按照選擇器查找符合條件的元素:
var firstElem=document.querySelector("CSS選擇器");
var elems=document.querySelectorAll("CSS選擇器");
原生API:底層實現!

vs 舊getxxxByXXX方法
舊getxxxByXXX方法:返回僅是實際元素對象的引用。還須返回樹結構中遍歷對象的屬性。
selectors API:返回結果包含完整的元素對象和屬性。不須要再返回樹中遍歷,便可訪問元素的全部屬性!

DEMO:二級菜單彈出
onmouseover: 鼠標進入元素邊界時,*發生一次*!
onmouseout: 鼠標移出元素邊界時,觸發一次

DOM樹的快速得到指定節點:
document.documentElement: 整個<html>的內容——瞭解
document.body:直接得到body元素!——重要

*爬樹:
向上爬:parentNode:
向下爬:querySelectorAll:*

元素樹:節點樹去掉屬性節點和文本節點後獲得的只有元素組成的樹。
節點樹 vs 元素樹:
父節點 parentNode parentElementNode
全部子節點 childNodes children
第一個子節點 firstChild firstElementChild
最後子節點 lastChild lastElementChild
前一個兄弟 previousSibling previousElementSibling
後一個兄弟 nextSibling nextElementSibling

動態建立節點:3步:1. 建立空節點:var newElem=document.createElement("標籤名");好比:var a=document.createElement("a"); <a></a>2. 設置節點對象必要屬性:好比:a.href="http://tmooc.cn";a.innerHTML="tmooc"; <a href="http://tmooc.cn">tmooc</a>*************************3. 將節點掛到指定父元素下*//向父元素末尾追加新元素parentNode.appendChild(newElem);//在父元素中間,插入新元素parentNode.insertBefore(newElem,後一個現有元素對象)

相關文章
相關標籤/搜索