DOM模型(三)—— Element節(jié)點

Element對象對應(yīng)網(wǎng)頁的HTML標(biāo)簽元素。每一個HTML標(biāo)簽元素,在DOM樹上都會轉(zhuǎn)化成一個Element節(jié)點對象(以下簡稱元素節(jié)點)。

元素節(jié)點的nodeType屬性都是1,但是不同HTML標(biāo)簽生成的元素節(jié)點時不一樣的。JS內(nèi)部使用不同的構(gòu)造函數(shù),生成不同的Element節(jié)點,比如<a>標(biāo)簽的節(jié)點對象由HTMLAnchorElement()構(gòu)造函數(shù)生成,<button>標(biāo)簽的節(jié)點對象由HTMLButtonElement()構(gòu)造函數(shù)生成。因此,元素節(jié)點不是一種對象,而是一組對象。

一、與元素本身特征相關(guān)的屬性


以下屬性與元素本身的特征相關(guān)。

1.1、Element.attributes

Element.attributes屬性返回一個類似數(shù)組的對象,成員是當(dāng)前元素節(jié)點的所有屬性節(jié)點。下一節(jié)將詳細(xì)介紹。

1.2、Element.id,Element.tagName

Element.id屬性返回指定元素的id屬性,該屬性可讀寫。

Element.tagName屬性返回指定元素的大寫標(biāo)簽名,與nodeName屬性的值相等。

// HTML代碼為
// <span id="myspan">Hello</span>
var span = document.getElementById('span');
span.id // "myspan"
span.tagName // "SPAN"
驗證

1.3、Element.innerHTML

Element.innerHTML屬性返回該元素包含的HTML代碼。該屬性可讀寫,常用來設(shè)置某個節(jié)點的內(nèi)容。

如果將該屬性設(shè)為空,等于刪除它包含的所有節(jié)點。

el.innerHTML = '';

上面代碼等于將el節(jié)點變成了一個空節(jié)點,el原來包含的節(jié)點被全部刪除。

注意,如果文本節(jié)點中包含&、小于號和大于號,innerHTML屬性會將它們轉(zhuǎn)為實體形式&、<>。

// HTML代碼如下 <p id="para"> 5 > 3 </p>
document.getElementById('para').innerHTML
// 5 > 3

由于上面這個原因,導(dǎo)致用innerHTML插入<script>標(biāo)簽,不會被執(zhí)行。

var name = "<script>alert('haha')</script>";
el.innerHTML = name;

上面代碼將腳本插入內(nèi)容,腳本并不會執(zhí)行。但是,innerHTML還是有安全風(fēng)險的。

var name = "<img src=x onerror=alert(1)>";
el.innerHTML = name;

上面代碼中,alert方法是會執(zhí)行的。因此為了安全考慮,如果插入的事文本,最好用textContent屬性代替innerHTML。

1.4、Element.outerHTML

Element.outerHTML屬性返回一個字符串,內(nèi)容為指定元素節(jié)點的所有HTML代碼,包括它自身和包含的所有子元素。

// HTML代碼如下
// <div id="d"><p>Hello</p></div>

d = document.getElementById('d');
d.outerHTML
// '<div id="d"><p>Hello</p></div>'

outerHTML屬性是可讀寫的,對它進行賦值,等于替換掉當(dāng)前元素。

// 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屬性重新賦值以后,內(nèi)層的div元素就不存在了,被p元素替換了。但是,變量d依然指向原來的div元素,這表示被替換的DIV元素還存在于內(nèi)存中。

1.5、Element.className,Element.classList

className屬性用來讀寫當(dāng)前元素節(jié)點的class屬性。它的值是一個字符串,每個class之間用空格分割。

classList屬性則返回一個類似數(shù)組的對象,當(dāng)前元素節(jié)點的每個class就是這個對象的一個成員。

<div class="one two three" id="myDiv"></div>

上面這個div元素節(jié)點對象的className屬性和classList屬性,分別如下。

document.getElementById('myDiv').className
// "one two three"

document.getElementById('myDiv').classList
// {
//   0: "one"
//   1: "two"
//   2: "three"
//   length: 3
// }

從上面代碼可以看出,className屬性返回一個空格分隔的字符串,而classList屬性指向一個類似數(shù)組的對象,該對象的length屬性(只讀)返回當(dāng)前元素的class數(shù)量。

classList對象有下列方法。

add():增加一個class。
remove():移除一個class。
contains():檢查當(dāng)前元素是否包含某個class。
toggle():將某個class移入或移出當(dāng)前元素。
item():返回指定索引位置的class。

toString():將class的列表轉(zhuǎn)為字符串。

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方法可以接受一個布爾值,作為第二個參數(shù)。如果為true,則添加該屬性;如果為false,則去除該屬性。

el.classList.toggle('abc', boolValue);

// 等同于

if (boolValue){
  el.classList.add('abc');
} else {
  el.classList.remove('abc');
}

二、盒狀模型相關(guān)屬性


2.1、Element.clientHeight,Element.clientWidth

Element.clientHeight屬性返回元素節(jié)點可見部分的高度,Element.clientWidth屬性返回元素節(jié)點可見部分的寬度。所謂可見部分,指的是不包括溢出的大小,只返回該元素在容器中占據(jù)的大小,對于有滾動條的元素來說,它們等于滾動條圍起來的區(qū)域大小。這兩個屬性的值包括Padding、但不包括滾動條、邊框和Margin,單位為像素。這兩個屬性可以計算得到,等于元素的CSS高度(或?qū)挾龋┘由螩SS的padding,減去滾動條(如果存在)。

對于整張網(wǎng)頁來說,當(dāng)前可見高度(即視口高度)要從document.documentElement對象(即<html>節(jié)點)上獲取,等同于window.innerHeight屬性減去水平滾動條的高度。沒有滾動條時,這兩個值是相等的;有滾動條時,前者小于后者。

2.2、Element.clientLeft,Element.clientTop

2.3、Element.scrollHeight,Element.scrollWidth

2.4、Element.scrollLeft,Element.scrollTop

2.5、Element.offsetHeight,Element.offsetWidth

2.6、Element.offsetLeft,Element.offsetTop

2.7、Element.style

每個元素節(jié)點都有style用來讀寫該元素的行內(nèi)樣式信息。

2.8、總結(jié)

三、返回元素節(jié)點相關(guān)節(jié)點的屬性


以下屬性返回元素節(jié)點的相關(guān)節(jié)點。

3.1、Element.children,Element.childElementCount

Element.children屬性返回一個HTMLCollection對象,包括當(dāng)前元素節(jié)點的所有子節(jié)點。它是一個類似數(shù)組的動態(tài)對象(實時反映網(wǎng)頁元素的變化)。如果當(dāng)前元素沒有子元素,則返回的對象包含零個成員。

// para是一個p元素節(jié)點
if (para.children.length) {
  var children = para.children;
    for (var i = 0; i < children.length; i++) {
      // ...
    }
}

這個屬性與Node.childNodes屬性的區(qū)別是,它只包括HTML元素類型的子節(jié)點,不包括其他類型的子節(jié)點。

Element.childElementCount屬性返回當(dāng)前元素節(jié)點包含的子HTML元素節(jié)點的個數(shù),與Element.children.length的值相同。注意,該屬性只計算HTML元素類型的子節(jié)點。

3.2、Element.firstElementChild,Element.lastElementChild

Element.firstElementChild屬性返回第一個HTML元素類型的子節(jié)點,Element.lastElementChild返回最后一個HTML元素類型的子節(jié)點。

如果沒有HTML類型的子節(jié)點,這兩個屬性返回null。

3.3、Element.nextElementSibling,Element.previousElementSibling

Element.nextElementSibling屬性返回當(dāng)前HTML元素節(jié)點的后一個同級HTML元素節(jié)點,如果沒有則返回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>

Element.previousElementSibling屬性返回當(dāng)前HTML元素節(jié)點的前一個同級HTML元素節(jié)點,如果沒有則返回null。

3.4、Element.offsetParent

Element.offsetParent屬性返回當(dāng)前HTML元素的最靠近的、并且CSS的position屬性不等于static的父元素。如果某個元素的所有上層節(jié)點都將position屬性設(shè)為static,則Element.offsetParent屬性指向<body>元素。

該屬性主要用于確定子元素的位置偏移,是Element.offsetTopElement.offsetLeft的計算基準(zhǔn)。

四、操作元素屬性相關(guān)的方法


元素節(jié)點提供以下四個方法,用來操作HTML標(biāo)簽的屬性。

  • Element.getAttribute():讀取指定屬性
  • Element.setAttribute():設(shè)置指定屬性
  • Element.hasAttribute():返回一個布爾值,表示當(dāng)前元素節(jié)點是否有指定的屬性
  • Element.removeAttribute():移除指定屬性

五、查找相關(guān)的方法


以下四個方法用來查找與當(dāng)前元素節(jié)點相關(guān)的節(jié)點。這四個方法也部署在document對象上,用法完全一致。

  • Element.querySelector()
  • Element.querySelectorAll()
  • Element.getElementByTagName()
  • Element.getElementByClassName()

上面四個方法只返回Element子節(jié)點,因此可以采用鏈?zhǔn)綄懛ā?/p>

document
  .getElementById('header')
  .getElementsByClassName('a')

5.1、Element.querySelector()

Element.querySelector方法接受CSS選擇器作為參數(shù),返回父元素的第一個匹配的子元素。

var content = document.getElementById('content');
var el = content.querySelector('p');

上面代碼返回content節(jié)點的第一個p元素。

需要注意的是,瀏覽器執(zhí)行querySelector方法時,是先在全局范圍內(nèi)搜索給定的CSS選擇器,然后過濾出哪些屬于當(dāng)前元素的子元素。因此,會有一些違反直覺的結(jié)果。

<div>
<blockquote id="outer">
  <p>Hello</p>
  <div id="inner">
    <p>World</p>
  </div>
</blockquote>
</div>

那么,下面代碼實際上會返回第一個p元素,而不是第二個。

var outer = document.getElementById('outer');
outer.querySelector('div p')
// <p>Hello</p>
選擇器最好夠明確

5.2、Element.querySelectorAll()

Element.querySelectorAll方法接受CSS選擇器作為參數(shù),返回一個NodeList對象,包含所有匹配的子元素。

該方法的執(zhí)行機制與querySelector相同,也是先在全局范圍內(nèi)查找,再過濾出當(dāng)前元素的子元素。因此,選擇器實際上針對整個文檔的。

5.3、Element.getElementsByTagName()

Element.getElementsByTagName方法返回一個HTMLCollection對象,成員是當(dāng)前元素節(jié)點的所有匹配指定標(biāo)簽名的子元素。該方法與document.getElementsByTagName方法的用法類似,只是搜索范圍不是整個文檔,而是當(dāng)前元素節(jié)點。

同樣的,該方法的參數(shù)大小寫不敏感。

5.4、Element.getElementsByClassName()

Element.getElementsByClassName方法返回一個HTMLCollection對象,成員是當(dāng)前元素節(jié)點的所有匹配指定class的子元素。該方法與document.getElementsByClassName方法的用法類似,只是搜索范圍不是整個文檔,而是當(dāng)前元素節(jié)點。

該方法的參數(shù)大小寫敏感。

5.5、Element.closest()

Element.closest方法返回當(dāng)前元素節(jié)點的最接近的父元素(或者當(dāng)前節(jié)點本身),條件是必須匹配給定的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>

//JS代碼
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方法將當(dāng)前元素節(jié)點也考慮在內(nèi),所以第二個closet方法返回div-03。

5.6、Element.match()

Element.match方法返回一個布爾值,表示當(dāng)前元素是否匹配給定的CSS選擇器。

六、事件相關(guān)的方法


以下三個方法與Element節(jié)點的事件相關(guān)。這些方法都繼承自EventTarget接口。

  • Element.addEventListener():添加事件的回調(diào)函數(shù)
  • Element.removeEventListener():移除事件監(jiān)聽函數(shù)
  • Element.dispatchEvent():觸發(fā)事件
element.addEventListener('click', listener, false);
element.removeEventListener('click', listener, false);

var event = new Event('click');
element.dispatchEvent(event);

七、其他方法


7.1、Element.scrollIntoView()

7.2、Element.getBoundingClientRect()

7.3、Element.getClientRects()

7.4、Element.insertAdjacentHTML()

7.5、Element.remove()

Element.remove方法用于將當(dāng)前元素節(jié)點從DOM樹刪除。

var el = document.getElementById('div-01');
el.remove();

7.6、Element.focus()

Element.focus方法用于將當(dāng)前頁面的焦點,轉(zhuǎn)移到指定元素上。

document.getElementById('my-span').focus();
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容