Element對象對應網頁的HTML標簽元素。每一個HTML標簽元素,在DOM樹上都會轉化成一個Element節點對象(以下簡稱元素節點)。元素節點的nodeType屬性都是1,但是不同HTML標簽生成的元素節點是不一樣的。JavaScript內部使用不同的構造函數,生成不同的Element節點,比如a標簽的節點對象由HTMLAnchorElement()構造函數生成,button標簽的節點對象由HTMLButtonElement()構造函數生成。因此,元素節點不是一種對象,而是一組對象。
[TOC]
## 屬性
### attributes,id,tagName
以下屬性返回元素節點的性質。
(1)attributes
attributes屬性返回一個類似數組的對象,成員是當前元素節點的所有屬性節點,每個數字索引對應一個屬性節點(Attribute)對象。返回值中,所有成員都是動態的,即屬性的變化會實時反映在結果集。
下面是一個HTML代碼。
~~~
<p id="para">Hello World</p>
~~~
獲取attributes成員的代碼如下。
~~~
var para = document.getElementById('para');
var attr = para.attributes[0];
attr.name // id
attr.value // para
~~~
上面代碼說明,通過attributes屬性獲取屬性節點對象(attr)以后,可以通過name屬性獲取屬性名(id),通過value屬性獲取屬性值(para)。
注意,屬性節點的name屬性和value屬性,等同于nodeName屬性和nodeValue屬性。
下面代碼是遍歷一個元素節點的所有屬性。
~~~
var para = document.getElementsByTagName("p")[0];
if (para.hasAttributes()) {
var attrs = para.attributes;
var output = "";
for(var i = attrs.length - 1; i >= 0; i--) {
output += attrs[i].name + "->" + attrs[i].value;
}
result.value = output;
} else {
result.value = "No attributes to show";
}
~~~
(2)id屬性
id屬性返回指定元素的id標識。該屬性可讀寫。
(3)tagName屬性
tagName屬性返回指定元素的大寫的標簽名,與nodeName屬性的值相等。
~~~
// 假定HTML代碼如下
// <span id="span">Hello</span>
var span = document.getElementById("span");
span.tagName // "SPAN"
~~~
### innerHTML,outerHTML
以下屬性返回元素節點的HTML內容。
(1)innerHTML
innerHTML屬性返回該元素包含的HTML代碼。該屬性可讀寫,常用來設置某個節點的內容。
如果將該屬性設為空,等于刪除所有它包含的所有節點。
~~~
el.innerHTML = '';
~~~
上面代碼等于將el節點變成了一個空節點,el原來包含的節點被全部刪除。
注意,如果文本節點中包含&、小于號(<)和大于號(%gt;),innerHTML屬性會將它們轉為實體形式&、<、>。
~~~
// HTML代碼如下 <p id="para"> 5 > 3 </p>
document.getElementById('para').innerHTML
// 5 > 3
~~~
由于上面這個原因,導致在innerHTML插入標簽,不會被執行。
~~~
var name = "<script>alert('haha')</script>";
el.innerHTML = name;
~~~
上面代碼將腳本插入內容,腳本并不會執行。但是,innerHTML還是有安全風險的。
~~~
var name = "<img src=x onerror=alert(1)>";
el.innerHTML = name;
~~~
上面代碼中,alert方法是會執行的。因此為了安全考慮,如果插入的是文本,最好用textContent屬性代替innerHTML。
(2)outerHTML
outerHTML屬性返回一個字符串,內容為指定元素的所有HTML代碼,包括它自身和包含的所有子元素。
~~~
// 假定HTML代碼如下
// <div id="d"><p>Hello</p></div>
d = document.getElementById("d");
dump(d.outerHTML);
// '<div id="d"><p>Hello</p></div>'
~~~
outerHTML屬性是可讀寫的,對它進行賦值,等于替換掉當前元素。
~~~
// 假定HTML代碼如下
// <div id="container"><div id="d">Hello</div></div>
container = document.getElementById("container");
d = document.getElementById("d");
container.firstChild.nodeName // "DIV"
d.nodeName // "DIV"
d.outerHTML = "<p>Hello</p>";
container.firstChild.nodeName // "P"
d.nodeName // "DIV"
~~~
上面代碼中,outerHTML屬性重新賦值以后,內層的div元素就不存在了,被p元素替換了。但是,變量d依然指向原來的div元素,這表示被替換的DIV元素還存在于內存中。
如果指定元素沒有父節點,對它的outerTHML屬性重新賦值,會拋出一個錯誤。
~~~
document.documentElement.outerHTML = "test"; // DOMException
~~~
### children,childElementCount,firstElementChild,lastElementChild
以下屬性與元素節點的子元素相關。
(1)children
children屬性返回一個類似數組的動態對象(實時反映變化),包括當前元素節點的所有子元素。如果當前元素沒有子元素,則返回的對象包含零個成員。
~~~
// para是一個p元素節點
if (para.children.length) {
var children = para.children;
for (var i = 0; i < children.length; i++) {
// ...
}
}
~~~
(2)childElementCount
childElementCount屬性返回當前元素節點包含的子元素節點的個數。
(3)firstElementChild
firstElementChild屬性返回第一個子元素,如果沒有,則返回null。
(4)lastElementChild
lastElementChild屬性返回最后一個子元素,如果沒有,則返回null。
### nextElementSibling,previousElementSibling
以下屬性與元素節點的同級元素相關。
(1)nextElementSibling
nextElementSibling屬性返回指定元素的后一個同級元素,如果沒有則返回null。
~~~
// 假定HTML代碼如下
// <div id="div-01">Here is div-01</div>
// <div id="div-02">Here is div-02</div>
var el = document.getElementById('div-01');
el.nextElementSibling
// <div id="div-02">Here is div-02</div>
~~~
(2)previousElementSibling
previousElementSibling屬性返回指定元素的前一個同級元素,如果沒有則返回null。
### className,classList
className屬性用來讀取和設置當前元素的class屬性。它的值是一個字符串,每個class之間用空格分割。
classList屬性則返回一個類似數組的對象,當前元素節點的每個class就是這個對象的一個成員。
~~~
<div class="one two three" id="myDiv"></div>
~~~
上面這個div元素的節點對象的className屬性和classList屬性,分別如下。
~~~
document.getElementById('myDiv').className
// "one two three"
document.getElementById('myDiv').classList
// {
// 0: "one"
// 1: "two"
// 2: "three"
// length: 3
// }
~~~
從上面代碼可以看出,className屬性返回一個空格分隔的字符串,而classList屬性指向一個類似數組的對象,該對象的length屬性(只讀)返回當前元素的class數量。
classList對象有下列方法。
* add():增加一個class。
* remove():移除一個class。
* contains():檢查當前元素是否包含某個class。
* toggle():將某個class移入或移出當前元素。
* item():返回指定索引位置的class。
* toString():將class的列表轉為字符串。
~~~
myDiv.classList.add('myCssClass');
myDiv.classList.add('foo', 'bar');
myDiv.classList.remove('myCssClass');
myDiv.classList.toggle('myCssClass'); // 如果myCssClass不存在就加入,否則移除
myDiv.classList.contains('myCssClass'); // 返回 true 或者 false
myDiv.classList.item(0); // 返回第一個Class
myDiv.classList.toString();
~~~
下面比較一下,className和classList在添加和刪除某個類時的寫法。
~~~
// 添加class
document.getElementById('foo').className += 'bold';
document.getElementById('foo').classList.add('bold');
// 刪除class
document.getElementById('foo').classList.remove('bold');
document.getElementById('foo').className =
document.getElementById('foo').className.replace(/^bold$/, '');
~~~
toggle方法可以接受一個布爾值,作為第二個參數。如果為true,則添加該屬性;如果為false,則去除該屬性。
~~~
el.classList.toggleClass("abc", someBool);
// 等同于
if (someBool){
el.classList.add("abc");
} else {
el.classList.remove("abc");
}
~~~
### clientHeight,clientLeft,clientTop,clientWidth
以下屬性與元素節點的可見區域的坐標相關。
(1)clientHeight
clientHeight屬性返回元素節點的可見高度,包括padding、但不包括水平滾動條、邊框和margin的高度,單位為像素。該屬性可以計算得到,等于元素的CSS高度,加上CSS的padding高度,減去水平滾動條的高度(如果存在水平滾動條)。
如果一個元素是可以滾動的,則clientHeight只計算它的可見部分的高度。
(2)clientLeft
clientLeft屬性等于元素節點左邊框(border)的寬度,單位為像素,包括垂直滾動條的寬度,不包括左側的margin和padding。但是,除非排版方向是從右到左,且發生元素寬度溢出,否則是不可能存在左側滾動條。如果該元素的顯示設為`display: inline`,clientLeft一律為0,不管是否存在左邊框。
(3)clientTop
clientTop屬性等于網頁元素頂部邊框的寬度,不包括頂部的margin和padding。
(4)clientWidth
clientWidth屬性等于網頁元素的可見寬度,即包括padding、但不包括垂直滾動條(如果有的話)、邊框和margin的寬度,單位為像素。
如果一個元素是可以滾動的,則clientWidth只計算它的可見部分的寬度。
### scrollHeight,scrollWidth,scrollLeft,scrollTop
以下屬性與元素節點占據的總區域的坐標相關。
(1)scrollHeight
scrollHeight屬性返回指定元素的總高度,包括由于溢出而無法展示在網頁的不可見部分。如果一個元素是可以滾動的,則scrollHeight包括整個元素的高度,不管是否存在垂直滾動條。scrollHeight屬性包括padding,但不包括border和margin。該屬性為只讀屬性。
如果不存在垂直滾動條,scrollHeight屬性與clientHeight屬性是相等的。如果存在滾動條,scrollHeight屬性總是大于clientHeight屬性。當滾動條滾動到內容底部時,下面的表達式為true。
~~~
element.scrollHeight - element.scrollTop === element.clientHeight
~~~
如果滾動條沒有滾動到內容底部,上面的表達式為false。這個特性結合`onscroll`事件,可以判斷用戶是否滾動到了指定元素的底部,比如是否滾動到了《使用須知》區塊的底部。
~~~
var rules = document.getElementById("rules");
rules.onscroll = checking;
function checking(){
if (this.scrollHeight - this.scrollTop === this.clientHeight) {
console.log('謝謝閱讀');
} else {
console.log('您還未讀完');
}
}
~~~
(2)scrollWidth
scrollWidth屬性返回元素的總寬度,包括由于溢出容器而無法顯示在網頁上的那部分寬度,不管是否存在水平滾動條。該屬性是只讀屬性。
(3)scrollLeft
scrollLeft屬性設置或返回水平滾動條向右側滾動的像素數量。它的值等于元素的最左邊與其可見的最左側之間的距離。對于那些沒有滾動條或不需要滾動的元素,該屬性等于0。該屬性是可讀寫屬性,設置該屬性的值,會導致瀏覽器將指定元素自動滾動到相應的位置。
(4)scrollTop
scrollTop屬性設置或返回垂直滾動條向下滾動的像素數量。它的值等于元素的頂部與其可見的最高位置之間的距離。對于那些沒有滾動條或不需要滾動的元素,該屬性等于0。該屬性是可讀寫屬性,設置該屬性的值,會導致瀏覽器將指定元素自動滾動到相應位置。
~~~
document.querySelector('div').scrollTop = 150;
~~~
上面代碼將div元素向下滾動150像素。
## 方法
### hasAttribute(),getAttribute(),removeAttribute(),setAttribute()
以下方法與元素節點的屬性相關。
(1)hasAttribute()
hasAttribute方法返回一個布爾值,表示當前元素節點是否包含指定的HTML屬性。
~~~
var d = document.getElementById("div1");
if (d.hasAttribute("align")) {
d.setAttribute("align", "center");
}
~~~
上面代碼檢查div節點是否含有align屬性。如果有,則設置為“居中對齊”。
(2)getAttribute()
getAttribute方法返回當前元素節點的指定屬性。如果指定屬性不存在,則返回null。
~~~
var div = document.getElementById("div1");
div.getAttribute("align") // "left"
~~~
(3)removeAttribute()
removeAttribute方法用于從當前元素節點移除屬性。
~~~
// 原來的HTML代碼
// <div id="div1" align="left" width="200px">
document.getElementById("div1").removeAttribute("align");
// 現在的HTML代碼
// <div id="div1" width="200px">
~~~
(4)setAttribute()
setAttribute方法用于為當前元素節點新增屬性,或編輯已存在的屬性。
~~~
var d = document.getElementById("d1");
d.setAttribute("align", "center");
~~~
該方法會將所有屬性名,都當作小寫處理。對于那些已存在的屬性,該方法是編輯操作,否則就會新建屬性。
大多數情況下,直接對屬性賦值比使用該方法更好。
~~~
el.value = 'hello';
// or
el.setAttribute('value', 'hello');
~~~
### querySelector(),querySelectorAll(),getElementsByClassName(),getElementsByTagName()
以下方法與獲取當前元素節點的子元素相關。
(1)querySelector()
querySelector方法接受CSS選擇器作為參數,返回父元素的第一個匹配的子元素。
~~~
var content = document.getElementById('content');
var el = content.querySelector('p');
~~~
上面代碼返回content節點的第一個p元素。
注意,如果CSS選擇器有多個組成部分,比如`div p`,querySelector方法會把父元素考慮在內。假定HTML代碼如下。
~~~
<div id="outer">
<p>Hello</p>
<div id="inner">
<p>World</p>
</div>
</div>
~~~
那么,下面代碼會選中第一個p元素。
~~~
var outer = document.getElementById('outer');
var el = outer.querySelector('div p');
~~~
(2)querySelectorAll()
querySelectorAll方法接受CSS選擇器作為參數,返回一個NodeList對象,包含所有匹配的子元素。
~~~
var el = document.querySelector('#test');
var matches = el.querySelectorAll('div.highlighted > p');
~~~
在CSS選擇器有多個組成部分時,querySelectorAll方法也是會把父元素本身考慮在內。
還是以上面的HTML代碼為例,下面代碼會同時選中兩個p元素。
~~~
var outer = document.getElementById('outer');
var el = outer.querySelectorAll('div p');
~~~
(3)getElementsByClassName()
getElementsByClassName方法返回一個HTMLCollection對象,成員是當前元素節點的所有匹配指定class的子元素。該方法與document.getElementsByClassName方法的用法類似,只是搜索范圍不是整個文檔,而是當前元素節點。
(4)getElementsByTagName()
getElementsByTagName方法返回一個HTMLCollection對象,成員是當前元素節點的所有匹配指定標簽名的子元素。該方法與document.getElementsByClassName方法的用法類似,只是搜索范圍不是整個文檔,而是當前元素節點。此外,該方法搜索之前,會統一將標簽名轉為小寫。
### closest(),matches()
(1)closest()
closest方法返回當前元素節點的最接近的父元素(或者當前節點本身),條件是必須匹配給定的CSS選擇器。如果不滿足匹配,則返回null。
假定HTML代碼如下。
~~~
<article>
<div id="div-01">Here is div-01
<div id="div-02">Here is div-02
<div id="div-03">Here is div-03</div>
</div>
</div>
</article>
~~~
div-03節點的closet方法的例子如下。
~~~
var el = document.getElementById('div-03');
el.closest("#div-02") // div-02
el.closest("div div") // div-03
el.closest("article > div") //div-01
el.closest(":not(div)") // article
~~~
上面代碼中,由于closet方法將當前元素節點也考慮在內,所以第二個closet方法返回div-03。
(2)match()
match方法返回一個布爾值,表示當前元素是否匹配給定的CSS選擇器。
~~~
if (el.matches(".someClass")) {
console.log("Match!");
}
~~~
該方法帶有瀏覽器前綴,下面的函數可以兼容不同的瀏覽器,并且在瀏覽器不支持時,自行部署這個功能。
~~~
function matchesSelector(el, selector) {
var p = Element.prototype;
var f = p.matches
|| p.webkitMatchesSelector
|| p.mozMatchesSelector
|| p.msMatchesSelector
|| function(s) {
return [].indexOf.call(document.querySelectorAll(s), this) !== -1;
};
return f.call(el, selector);
}
// 用法
matchesSelector(
document.getElementById('myDiv'),
'div.someSelector[some-attribute=true]'
)
~~~
### addEventListener(),removeEventListener(),dispatchEvent()
以下三個方法與Element節點的事件相關。這些方法都繼承自EventTarget接口,詳細介紹參見《Event對象》章節的《EventTarget》部分。
~~~
// 添加事件監聽函數
el.addEventListener('click', listener, false);
// 移除事件監聽函數
el.removeEventListener('click', listener, false);
// 觸發事件
var event = new Event('click');
el.dispatchEvent(event);
~~~
### getBoundingClientRect(),getClientRects()
以下方法返回元素節點的CSS盒狀模型信息。
(1)getBoundingClientRect()
getBoundingClientRect方法返回一個對象,該對象提供當前元素節點的大小、它相對于視口(viewport)的位置等信息,基本上就是CSS盒狀模型的內容。
~~~
var rect = obj.getBoundingClientRect();
~~~
上面代碼中,getBoundingClientRect方法返回的對象,具有以下屬性(全部為只讀)。
* bottom:元素底部相對于視口的縱坐標。
* height:元素高度(等于bottom減去top)。
* left:元素左上角相對于視口的坐標。
* right:元素右邊界相對于視口的橫坐標。
* top:元素頂部相對于視口的縱坐標。
* width:元素寬度(等于right減去left)。
由于元素相對于視口(viewport)的位置,會隨著頁面滾動變化,因此表示位置的四個屬性值,都不是固定不變的。
注意,getBoundingClientRect方法的所有屬性,都把邊框(border屬性)算作元素的一部分。也就是說,都是從邊框外緣的各個點來計算。因此,width和height包括了元素本身 + padding + border。
(1)getClientRects()
getClientRects方法返回一個類似數組的對象,里面是當前元素在頁面上形成的所有矩形。每個矩形都有botto、height、left、right、top和width六個屬性,表示它們相對于視口的四個坐標,以及本身的高度和寬度。
對于盒狀元素(比如div和p),該方法返回的對象中只有該元素一個成員。對于行內元素(比如span、a、em),該方法返回的對象有多少個成員,取決于該元素在頁面上占據多少行。
~~~
<span id="inline">
Hello World
Hello World
Hello World
</span>
~~~
上面代碼是一個行內元素span,如果它在頁面上占據三行,getClientRects方法返回的對象就有三個成員,如果它在頁面上占據一行,getClientRects方法返回的對象就只有一個成員。
~~~
var el = document.getElementById('inline');
el.getClientRects().length // 3
el.getClientRects()[0].left // 8
el.getClientRects()[0].right // 113.908203125
el.getClientRects()[0].bottom // 31.200000762939453
el.getClientRects()[0].height // 23.200000762939453
el.getClientRects()[0].width // 105.908203125
~~~
這個方法主要用于判斷行內元素是否換行,以及行內元素的每一行的位置偏移。
### insertAdjacentHTML(),remove()
以下方法操作元素節點的DOM樹。
(1)insertAdjacentHTML()
insertAdjacentHTML方法解析字符串,然后將生成的節點插入DOM樹的指定位置。
~~~
element.insertAdjacentHTML(position, text);
~~~
該方法接受兩個參數,第一個是指定位置,第二個是待解析的字符串。
指定位置共有四個。
* beforebegin:在當前元素節點的前面。
* afterbegin:在當前元素節點的里面,插在它的第一個子元素之前。
* beforeend:在當前元素節點的里面,插在它的最后一個子元素之后。
* afterend:在當前元素節點的后面。'
~~~
// 原來的HTML代碼:<div id="one">one</div>
var d1 = document.getElementById('one');
d1.insertAdjacentHTML('afterend', '<div id="two">two</div>');
// 現在的HTML代碼:
// <div id="one">one</div><div id="two">two</div>
~~~
該方法不是徹底置換現有的DOM結構,這使得它的執行速度比innerHTML操作快得多。所有瀏覽器都支持這個方法,包括IE 6。
(2)remove()
remove方法用于將當前元素節點從DOM樹刪除。
~~~
var el = document.getElementById('div-01');
el.remove();
~~~
### scrollIntoView()
scrollIntoView方法滾動當前元素,進入瀏覽器的可見區域。
~~~
el.scrollIntoView(); // 等同于el.scrollIntoView(true)
el.scrollIntoView(false);
~~~
該方法可以接受一個布爾值作為參數。如果為true,表示元素的頂部與當前區域的可見部分的頂部對齊(前提是當前區域可滾動);如果為false,表示元素的底部與當前區域的可見部分的尾部對齊(前提是當前區域可滾動)。如果沒有提供該參數,默認為true。
- 第一章 導論
- 1.1 前言
- 1.2 為什么學習JavaScript?
- 1.3 JavaScript的歷史
- 第二章 基本語法
- 2.1 語法概述
- 2.2 數值
- 2.3 字符串
- 2.4 對象
- 2.5 數組
- 2.6 函數
- 2.7 運算符
- 2.8 數據類型轉換
- 2.9 錯誤處理機制
- 2.10 JavaScript 編程風格
- 第三章 標準庫
- 3.1 Object對象
- 3.2 Array 對象
- 3.3 包裝對象和Boolean對象
- 3.4 Number對象
- 3.5 String對象
- 3.6 Math對象
- 3.7 Date對象
- 3.8 RegExp對象
- 3.9 JSON對象
- 3.10 ArrayBuffer:類型化數組
- 第四章 面向對象編程
- 4.1 概述
- 4.2 封裝
- 4.3 繼承
- 4.4 模塊化編程
- 第五章 DOM
- 5.1 Node節點
- 5.2 document節點
- 5.3 Element對象
- 5.4 Text節點和DocumentFragment節點
- 5.5 Event對象
- 5.6 CSS操作
- 5.7 Mutation Observer
- 第六章 瀏覽器對象
- 6.1 瀏覽器的JavaScript引擎
- 6.2 定時器
- 6.3 window對象
- 6.4 history對象
- 6.5 Ajax
- 6.6 同域限制和window.postMessage方法
- 6.7 Web Storage:瀏覽器端數據儲存機制
- 6.8 IndexedDB:瀏覽器端數據庫
- 6.9 Web Notifications API
- 6.10 Performance API
- 6.11 移動設備API
- 第七章 HTML網頁的API
- 7.1 HTML網頁元素
- 7.2 Canvas API
- 7.3 SVG 圖像
- 7.4 表單
- 7.5 文件和二進制數據的操作
- 7.6 Web Worker
- 7.7 SSE:服務器發送事件
- 7.8 Page Visibility API
- 7.9 Fullscreen API:全屏操作
- 7.10 Web Speech
- 7.11 requestAnimationFrame
- 7.12 WebSocket
- 7.13 WebRTC
- 7.14 Web Components
- 第八章 開發工具
- 8.1 console對象
- 8.2 PhantomJS
- 8.3 Bower:客戶端庫管理工具
- 8.4 Grunt:任務自動管理工具
- 8.5 Gulp:任務自動管理工具
- 8.6 Browserify:瀏覽器加載Node.js模塊
- 8.7 RequireJS和AMD規范
- 8.8 Source Map
- 8.9 JavaScript 程序測試
- 第九章 JavaScript高級語法
- 9.1 Promise對象
- 9.2 有限狀態機
- 9.3 MVC框架與Backbone.js
- 9.4 嚴格模式
- 9.5 ECMAScript 6 介紹
- 附錄
- 10.1 JavaScript API列表
- 草稿一:函數庫
- 11.1 Underscore.js
- 11.2 Modernizr
- 11.3 Datejs
- 11.4 D3.js
- 11.5 設計模式
- 11.6 排序算法
- 草稿二:jQuery
- 12.1 jQuery概述
- 12.2 jQuery工具方法
- 12.3 jQuery插件開發
- 12.4 jQuery.Deferred對象
- 12.5 如何做到 jQuery-free?
- 草稿三:Node.js
- 13.1 Node.js 概述
- 13.2 CommonJS規范
- 13.3 package.json文件
- 13.4 npm模塊管理器
- 13.5 fs 模塊
- 13.6 Path模塊
- 13.7 process對象
- 13.8 Buffer對象
- 13.9 Events模塊
- 13.10 stream接口
- 13.11 Child Process模塊
- 13.12 Http模塊
- 13.13 assert 模塊
- 13.14 Cluster模塊
- 13.15 os模塊
- 13.16 Net模塊和DNS模塊
- 13.17 Express框架
- 13.18 Koa 框架