因?yàn)?DOM 的存在,這使我們可以通過 JavaScript 來獲取、創(chuàng)建、修改、或刪除節(jié)點(diǎn)。
NOTE:下面提供的例子中的 element
均為元素節(jié)點(diǎn)。
父子關(guān)系
element.parentNode
element.firstChild
/element.lastChild
element.childNodes
/element.children
兄弟關(guān)系
element.previousSibling
/element.nextSibling
element.previousElementSibling
/element.nextElementSibling
通過節(jié)點(diǎn)直接的關(guān)系獲取節(jié)點(diǎn)會導(dǎo)致代碼維護(hù)性大大降低(節(jié)點(diǎn)之間的關(guān)系變化會直接影響到獲取節(jié)點(diǎn)),而通過接口則可以有效的解決此問題。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>ELEMENT_NODE & TEXT_NODE</title>
</head>
<body>
<ul id="ul">
<li>First</li>
<li>Second</li>
<li>Third</li>
<li>Fourth</li>
</ul>
<p>Hello</p>
<script type="text/javascript">
var ulNode = document.getElementsByTagName("ul")[0];
console.log(ulNode.parentNode); //<body></body>
console.log(ulNode.previousElementSibling); //null
console.log(ulNode.nextElementSibling); //<p>Hello</p>
console.log(ulNode.firstElementChild); //<li>First</li>
console.log(ulNode.lastElementChild); //<li>Fourth</li>
</script>
</body>
</html>
NTOE:細(xì)心地人會發(fā)現(xiàn),在節(jié)點(diǎn)遍歷的例子中,body、ul、li、p節(jié)點(diǎn)之間是沒有空格的,因?yàn)槿绻锌崭?,那么空格就會被?dāng)做一個TEXT節(jié)點(diǎn),從而用ulNode.previousSibling獲取到得就是一個空的文本節(jié)點(diǎn),而不是 <li>First</li>
節(jié)點(diǎn)了。即節(jié)點(diǎn)遍歷的幾個屬性會得到所有的節(jié)點(diǎn)類型,而元素遍歷只會得到相對應(yīng)的元素節(jié)點(diǎn)。一般情況下,用得比較多得還是元素節(jié)點(diǎn)的遍歷屬性。
實(shí)現(xiàn)瀏覽器兼容版的element.children
有一些低版本的瀏覽器并不支持 element.children
方法,但我們可以用下面的方式來實(shí)現(xiàn)兼容。
<html lang>
<head>
<meta charest="utf-8">
<title>Compatible Children Method</title>
</head>
<body id="body">
<div id="item">
<div>123</div>
<p>ppp</p>
<h1>h1</h1>
</div>
<script type="text/javascript">
function getElementChildren(e){
if(e.children){
return e.children;
}else{
/* compatible other browse */
var i, len, children = [];
var child = element.firstChild;
if(child != element.lastChild){
while(child != null){
if(child.nodeType == 1){
children.push(child);
}
child = child.nextSibling;
}
}else{
children.push(child);
}
return children;
}
}
/* Test method getElementChildren(e) */
var item = document.getElementById("item");
var children = getElementChildren(item);
for(var i =0; i < children.length; i++){
alert(children[i]);
}
</script>
</body>
</html>
NOTE:此兼容方法為初稿,還未進(jìn)行兼容性測試。
getElementById
getElementsByTagName
getElementsByClassName
querySelector
querySelectorAll
API | 只作用于 document | 唯一返回值 | live |
---|---|---|---|
getElementById | √ | √ | |
getElementsByTagName | √ | ||
getElementsByClassName | √ | ||
querySelectorAll | |||
querySelector | √ |
獲取文檔中指定 id
的節(jié)點(diǎn)對象。
var element = document.getElementById('id');
動態(tài)的獲取具有指定標(biāo)簽元素節(jié)點(diǎn)的集合(其返回值會被 DOM 的變化所影響,其值會發(fā)生變化)。此接口可直接通過元素而獲取,不必直接作用于 document
之上。
// 示例
var collection = element.getElementsByTagName('tagName');
// 獲取指定元素的所有節(jié)點(diǎn)
var allNodes = document.getElementsByTagName('*');
// 獲取所有 p 元素的節(jié)點(diǎn)
var elements = document.getElementsByTagName('p');
// 取出第一個 p 元素
var p = elements[0];
獲取指定元素中具有指定 class
的所有節(jié)點(diǎn)。多個 class
可的選擇可使用空格分隔,與順序無關(guān)。
var elements = element.getElementsByClassName('className');
NOTE:IE9 及一下版本不支持 getElementsByClassName
兼容方法
function getElementsByClassName(root, className) {
// 特性偵測
if (root.getElementsByClassName) {
// 優(yōu)先使用 W3C 規(guī)范接口
return root.getElementsByClassName(className);
} else {
// 獲取所有后代節(jié)點(diǎn)
var elements = root.getElementsByTagName('*');
var result = [];
var element = null;
var classNameStr = null;
var flag = null;
className = className.split(' ');
// 選擇包含 class 的元素
for (var i = 0, element; element = elements[i]; i++) {
classNameStr = ' ' + element.getAttribute('class') + ' ';
flag = true;
for (var j = 0, name; name = className[j]; j++) {
if (classNameStr.indexOf(' ' + name + ' ') === -1) {
flag = false;
break;
}
}
if (flag) {
result.push(element);
}
}
return result;
}
}
獲取一個 list
(其返回結(jié)果不會被之后 DOM 的修改所影響,獲取后不會再變化)符合傳入的 CSS 選擇器的第一個元素或全部元素。
var listElementNode = element.querySelector('selector');
var listElementsNodes = element.querySelectorAll('selector');
var sampleSingleNode = element.querySelector('#className');
var sampleAllNodes = element.querySelectorAll('#className');
NOTE: IE9 一下不支持 querySelector
與 querySelectorAll
創(chuàng)建節(jié)點(diǎn) -> 設(shè)置屬性 -> 插入節(jié)點(diǎn)
var element = document.createElement('tagName');
textContent
獲取或設(shè)置節(jié)點(diǎn)以及其后代節(jié)點(diǎn)的文本內(nèi)容(對于節(jié)點(diǎn)中的所有文本內(nèi)容)。
element.textContent; // 獲取
element.textContent = 'New Content';
NOTE:不支持 IE 9 及其一下版本。
innerText (不符合 W3C 規(guī)范)
獲取或設(shè)置節(jié)點(diǎn)以及節(jié)點(diǎn)后代的文本內(nèi)容。其作用于 textContent
幾乎一致。
element.innerText;
NOTE:不符合 W3C 規(guī)范,不支持 FireFox 瀏覽器。
FireFox 兼容方案
if (!('innerText' in document.body)) {
HTMLElement.prototype.__defineGetter__('innerText', function(){
return this.textContent;
});
HTMLElement.prototype.__defineSetter__('innerText', function(s) {
return this.textContent = s;
});
}
在指定的元素內(nèi)追加一個元素節(jié)點(diǎn)。
var aChild = element.appendChild(aChild);
在指定元素的指定節(jié)點(diǎn)前插入指定的元素。
var aChild = element.insertBefore(aChild, referenceChild);
刪除指定的節(jié)點(diǎn)的子元素節(jié)點(diǎn)。
var child = element.removeChild(child);
獲取或設(shè)置指定節(jié)點(diǎn)之中所有的 HTML 內(nèi)容。替換之前內(nèi)部所有的內(nèi)容并創(chuàng)建全新的一批節(jié)點(diǎn)(去除之前添加的事件和樣式)。innerHTML
不檢查內(nèi)容,直接運(yùn)行并替換原先的內(nèi)容。
NOTE:只建議在創(chuàng)建全新的節(jié)點(diǎn)時使用。不可在用戶可控的情況下使用。
var elementsHTML = element.innerHTML;
存在的問題
更多建議: