DOM(文檔對象模型)是針對HTML和XML文檔的一個API,描繪了一個層次化的節(jié)點樹,允許我們添加绢馍、移除和修改頁面的某一部分羹膳。目前流行的各種前端框架睡互,對于頁面結(jié)構(gòu)的調(diào)整更新構(gòu)建都是基于DOM的原生API來實現(xiàn)的,而我們平時在進(jìn)行前端開發(fā)時也或多或少會用到DOM原生操作陵像,尤其是“拋棄”jQuery
這個框架之后就珠,原生的DOM操作越來越重要,今天就來總結(jié)一些常見的DOM屬性和操作方法醒颖。
Node類型
DOM將文檔描繪成了一個多層次節(jié)點構(gòu)成的結(jié)構(gòu)妻怎,節(jié)點有很多的類型,每個類型又有不同的特點泞歉、數(shù)據(jù)和方法逼侦,節(jié)點之間也存在著相互的關(guān)系匿辩,同級關(guān)系,子父級關(guān)系等等榛丢。整個文檔就是由一個個節(jié)點構(gòu)建起來的樹铲球,就是我們經(jīng)常說的DOM樹。
每個節(jié)點(node)都有一個nodeType
屬性涕滋,表明節(jié)點的類型睬辐,下面先簡單列舉一下常見的節(jié)點類型:
- Node.ELEMENT_NODE(1)-----------元素節(jié)點,nodeType值為1
- Node.ATTRIBUTE_NODE(2)---------屬性節(jié)點宾肺,nodeType值為2
- Node.TEXT_NODE(3)--------------文本節(jié)點溯饵,nodeType值為3
- Node.COMMENT_NODE(8)-----------注釋節(jié)點,nodeType值為8
- Node.DOCUMENT_NODE(9)----------文檔節(jié)點锨用,nodeType值為9
- Node.DOCUMENT_TYPE_NODE(10)----doctype節(jié)點丰刊,nodeType值為10
可以通過節(jié)點的nodeType
值來判斷節(jié)點類型
if(someNode.nodeType == 1){
console.log("Node is an element.")
}
節(jié)點關(guān)系
節(jié)點之間存在著這樣或那樣的關(guān)系,每個node都有一個childNodes
屬性增拥,其中保存著一個NodeList
對象啄巧,有length
屬性,但不是一個Array
實例掌栅,可以像下面一樣訪問里面存著的node:
var fistChild = someNode.childNodes[0];
var secondChild = someNode.childNodes.item(1);
var count = someNode.childNodes.length;
還有一些屬性:
-
someNode.nextSibling
同級下一個節(jié)點 -
someNode.previousSibling
同級前一個節(jié)點 -
someNode.firstChild
節(jié)點的第一個子節(jié)點 -
someNode.lastChild
節(jié)點的最后一個子節(jié)點 -
someNode.parentNode
節(jié)點的父節(jié)點
節(jié)點操作方法
常見的操作方法
-
someNode.appendChild(newNode)
--------------在節(jié)點的childNodes末尾添加一個新節(jié)點秩仆,返回new -
someNode.insertBefore(newNode, whoNode)
----在who前面添加一個new節(jié)點,返回new -
someNode.replaceChild(newNode, whoNode)
----將who替換為new節(jié)點猾封,返回who -
someNode.removeChild(whoNode)
--------------將who移除澄耍,返回who
以上方法都是在父節(jié)點上的操作,沒有子節(jié)點節(jié)點調(diào)用這些方法會報錯晌缘。
兩個特例方法
這倆方法有沒有子節(jié)點都可以使用:
cloneNode()
這個方法用來復(fù)制調(diào)用它的節(jié)點齐莲,可以傳一個參數(shù)true來進(jìn)行深復(fù)制;
//淺復(fù)制磷箕,只復(fù)制節(jié)點本身选酗,不會復(fù)制節(jié)點內(nèi)部
var copyNode = someNode.cloneNode(false);
//深復(fù)制,復(fù)制節(jié)點內(nèi)部子節(jié)點
var deepCopy = someNode.cloneNode(true);
要注意的一點是岳枷,cloneNode
的默認(rèn)參數(shù)在不同的規(guī)范下芒填,取true和false都有可能,建議強制寫明參數(shù)空繁,不使用默認(rèn)值(其實也不知道默認(rèn)值到底是啥)氢烘。
normalize()
這個方法是文本節(jié)點(Text_Node)的專用方法,在someNode上調(diào)用時家厌,如果在其后代節(jié)點找到了空文本節(jié)點播玖,就刪除這個空文本節(jié)點;如果找到了相鄰的文本節(jié)點(一般來說直接寫的html都只有一個文本節(jié)點饭于,除非我們用createTextNode()這種方法創(chuàng)建文本節(jié)點蜀踏,才有可能出現(xiàn)相鄰的文本節(jié)點)维蒙,則合并為一個節(jié)點。
元素節(jié)點ELement_Node
其實元素節(jié)點簡單來說就是html中的標(biāo)簽果覆,什么p
標(biāo)簽颅痊,h1
標(biāo)簽等等,先說一下它的特性:
-
nodeType
值為1局待; -
nodeName
值為元素標(biāo)簽名斑响;也可以使用tagName
獲取,注意大小寫問題 -
nodeValue
值為null钳榨;它也沒啥值好用的 -
parentNode
可能為Document
或Element
舰罚;文檔的子節(jié)點或者其他element
的子節(jié)點 - 子節(jié)點可能是:
Element
、Text
薛耻、Comment
等等营罢;
HTML元素
所有的HTML元素都是由HTMLElement類型表示,它就是繼承自Element饼齿,然后添加了一些屬性饲漾,其實感覺跟ELement一個東西,主要有以下屬性:
- id;------------就是div的id么缕溉,標(biāo)識符一個
- title;---------就是那個title
- lang和dir;-----很少用
- className;-----class的名字結(jié)合
其中className
屬性考传,這個注意一下,返回的是一個class名稱的字符串合集证鸥,比如"item active test"伙菊,需要自己用字符串方法拆分操作它,后來HTML5就新增了一個classList
屬性敌土,返回的是個class數(shù)組,比['item', 'active', 'test']运翼,可以用數(shù)組的方式操作class名稱返干,就很方便了。
classList
屬性有自己的幾個操作方法:
-
add(value)
;----------將給定的字符串添加到列表血淌,如果有矩欠,則不添加 -
contains(value)
;-----列表里面有沒有給定的值,返回true/false -
remove(value)
;-------刪除列表中給定的值 -
toggle(value)
;-------沒有就添加悠夯,有就刪除
div.classList.remove('item');
div.classList.add('current');
div.classList.toggle('active');
操作特性
操作div元素的屬性癌淮,就是常見的幾種方法,列舉一下:
-
getAttribute()
; -
setAttribute()
; -
removeAttribute()
;
我們還經(jīng)常自定義屬性沦补,比如在標(biāo)簽里定義個id='1'
乳蓄,HTML5規(guī)范建議自定義屬性加上data-
前綴,表明是自定的屬性夕膀,這樣可以使用div.dataset.id
取得屬性值虚倒。
還有一個Attributes
屬性美侦,不展開說了,不怎么用到魂奥。
創(chuàng)建元素節(jié)點
可以使用document.createElement()
方法創(chuàng)建元素節(jié)點菠剩。再配合node的操作方法,進(jìn)行各種穿插耻煤。
屬性節(jié)點Attribute_Node
屬性節(jié)點不被認(rèn)為是DOM文檔樹的一部分具壮,簡單說一下它的特性:
-
nodeType
值為2; -
nodeName
值為特性的名稱哈蝇; -
nodeValue
值為特性的值棺妓; -
parentNode
為null - 沒有子節(jié)點
操作屬性一般用上面的getAttribute()
、setAttribute()
买鸽、removeAttribute()
涧郊。
文本節(jié)點Text_Node
文本節(jié)點簡單說就是標(biāo)簽里的內(nèi)容,比如<div>hello world</div>
中的'hello world'眼五,先說一下它的特性:
-
nodeType
值為3妆艘; -
nodeName
值為#text
; -
nodeValue
值為節(jié)點包含的文本; -
parentNode
可能Element
看幼; - 沒有子節(jié)點批旺;
開始和結(jié)束標(biāo)簽之間只要有內(nèi)容,就會創(chuàng)建一個文本節(jié)點:
//沒有文本節(jié)點
<div></div>
//有空格诵姜,故有一個文本節(jié)點
<div> </div>
//有內(nèi)容汽煮,故有一個文本節(jié)點
<div>hello world</div>
var textNode = div.firstChild;
textNode.nodeValue; // hello world
創(chuàng)建文本節(jié)點
可以通過document.createTextNode('hello world')
創(chuàng)建一個文本節(jié)點,再配合node的操作方法棚唆,進(jìn)行各種穿插暇赤。
一般來講,一個元素只有一個文本節(jié)點宵凌,但是你要是硬搞幾個相鄰節(jié)點鞋囊,也是可行的,然后就有了normalize()
和spliteText()
這倆方法:
var element = document.createElement('div');
element.className = 'message';
var textNode = document.createTextNode('hello world');
element.appendChild(textNode);
var anotherTextNode = document.createTextNode('Yep!');
element.appendChild(anotherTextNode); //這樣就有了倆文本節(jié)點
alert(element.childNodes.length); // 2
element.normalize();
alert(element.childNodes.length); // 1
alert(element.firstChild.nodeValue); // 'hello worldYep!'
spliteText()
是將文本節(jié)點進(jìn)行分割瞎惫,具體細(xì)節(jié)不想講了溜腐,碰見了再查。
文檔節(jié)點Document_Node
文檔節(jié)點表示整個HTML頁面瓜喇,document
對象也是window
對象的一個屬性挺益,說一下它的特性:
-
nodeType
值為9; -
nodeName
值為#document
; -
nodeValue
值為null乘寒; -
parentNode
值為null望众; - 子節(jié)點可能是一個
DocumentType
、Element
、Comment
黍檩;
子節(jié)點
document的子節(jié)點也就是常見的html
叉袍、head
、body
刽酱、doctype
等喳逛,可以用下面的屬性取得它們的引用:
var html = document.documentElement;
var head = document.head; // HTML5新定義的
var body = document.body;
var doctype = document.doctype;
文檔信息
僅做了解:
var originTitle = document.title; // 取得頁面的title
document.title = 'New Title'; // 設(shè)置頁面title
var url = document.URL; // 取得頁面的完整URL
var domin = document.domin; // 取得域名
var referrer = document.referrer; // 取得來源頁面的URL
查找元素
document.getElementById()
根據(jù)id獲取元素的引用,如果找不到棵里,就返回null润文,只能使用document
調(diào)用。
getElementsByTagName()
根據(jù)標(biāo)簽名獲取一個HTMLCollection
元素列表殿怜,跟NodeList
對象類似典蝌。可以使用document
或者element
調(diào)用
var images = document.getElementsByTagName('img'); // document調(diào)用
images.length; // 數(shù)量
images[0].src;
images.item(0).src;
var test = element.getElementsByTagName('a'); // element調(diào)用
還可以傳入一個*
來獲取文檔中的所有元素头谜。
getElementsByClassName()
根據(jù)class類名查找骏掀,可以使用document
或者element
調(diào)用
var test = document.getElementsByClassName("item active");
var test1 = element.getElementsByClassName("item");
DOM的擴展
DOM還有一個SelectorsAPI
的擴展,另一個是HTML5
柱告,下面說一下SelectorsAPI
截驮,都可以通過element
或者document
調(diào)用。
querySelector()
接受一個CSS選擇符际度,返回匹配到的第一個元素葵袭,沒有找到就返回null。
var body = document.querySelector('body');
var myDiv = document.querySelector('#myDiv');
querySelectorAll()
同樣接受一個CSS選擇符乖菱,返回一個NodeList
實例坡锡。
var ems = document.getElementById('myDiv').querySelectorAll('em');
var strongs = document.querySelectorAll('p strong');
strongs.item(1);
strongs[2];
文檔寫入
-
wirte()
; -
wirteIn()
;-----跟write()
一樣,只不過會在寫入的字符串最后添加一個'/n' -
close()
; -
open()
;
HTML5新增了innerHTML()
和outerHTML()
兩個方法窒所,不同的是outerHTML()
會包含調(diào)用元素本身鹉勒。另外一個需要了解的方法是contains()
,用來判斷某個節(jié)點是不是調(diào)用節(jié)點的子節(jié)點:
document.documentElement.contains(document.body); // true
本次先總結(jié)這些吵取,下次我們來總結(jié)一下原生操作樣式div.style.color
和關(guān)于offsetWidth
禽额、scrollTop
等的知識點。
歡迎沒事的時候來我的個人博客看一看