DOM相關知識點

此文目的


本文主要是整理DOM相關的知識點,方便往後的查看和各位的查缺補漏。因此重在整理,並不會展開。目前還在持續整理中,打算在16日左右完結。css

Node屬性和方法


  • nodeTypehtml

    Node.nodeType// 1爲元素節點,2爲屬性節點,3爲文本節點
  • nodeName與tagNamenode

    elementName = Element.tagName;//返回爲大寫標籤名,如DIV,IMG。通常用tagName便可。
    * Attr    ------ Attr.name    屬性名
    * Element ------ Element.tagName 標籤名
    * Text    ------ nodeName爲‘#text’,tagName爲undefined
  • nodeValuejquery

    * Text    ------ 文本內容
    * Element ------ null
  • attributes面試

//返回的是NamedNodeMap,不是ARRY。NamedNodeMap是字符串形式的名/值對。無序,且可自動更新。
//獲取參照mdn
var attr = element.attributes;
```
  • firstChild:表示某一節點的第一個節點
  • lastChild:表示某一節點的最後一個子節點
  • childNodes:表示所在節點的全部子節點
  • parentNode:表示所在節點的父節點
  • nextSibling:緊挨着當前節點的下一個節點
  • previousSibling:緊挨着當前節點的上一個節點

-方法:segmentfault

Node.hasChildNodes() // 若是包含子節點就返回true

DOM 建立


DOM節點(Node)一般對應於一個標籤,一個文本,或者一個HTML屬性。DOM節點有一個nodeType屬性用來表示當前元素的類型,它是一個整數:數組

  • Element,元素
  • Attribute,屬性
  • Text,文本

DOM節點建立最經常使用的即是document.createElement和document.createTextNode方法:瀏覽器

var el1 = document.createElement('div');
var node = document.createTextNode('hello world!');

DOM 查詢

getElementsByTagName等返回的實時的元素集合不須要預先得到全部的元素信息,而.querySelectorAll()會馬上收集全部的信息到一個靜態的列表裏,於是會[下降性能][2]。
能夠用instanceof操做符檢查節點的原型鏈:
```
myElement.firstChild.nodeType instanceof Text
```

元素查詢的API返回的的結果是DOM節點或者DOM節點的列表。app

//相似於css選擇器: 選擇classA下的classb元素
document.querySelector(".classA .classB");
// 返回選擇的第一個元素.myEl
var el = myEl.querySelector("#foo > div.bar");
// 返回一個文檔中a static NodeList,不是即時的
var els = myEl.querySelectorAll(".class");
//元素是否匹配選擇器
myElement.matches('div.bar') === true

// 返回的是HTMLCollection,即時更新的。
var el = document.getElementById('ID');
var els = document.getElementsByClassName('CLASS');
var els = document.getElementsByTagName('標籤名');
var els = document.getElementsByName('name屬性');

Element也提供了不少相對於元素的DOM導航方法:dom

// 獲取父元素、父節點
var parent = ele.parentNode;
var parent = ele.parentElement;//非標準

// 獲取子節點,子節點能夠是任何一種節點,能夠經過nodeType來判斷
var nodes = ele.children;//元素節點
var nodes = ele.childNodes; //全部節點,包括文本,元素等。可配合nodeType == 1獲得元素節點

// 當前元素的第一個/最後一個子元素節點
ele.firstElementChild;//第一個元素節點
ele.firstChild    //第一個節點,通常是文本節點
ele.lastElementChild;//最後一個元素節點
ele.lastChild//最後一個節點

// 下一個/上一個兄弟節點
var el = ele.nextElementSibling;//元素節點
var el = ele.nextSibling;//包括文本節點
var el = ele.previousElementSibling;
var el = ele.previousSibling;

DOM 更改


append,replace,insertBefor的參數el若是已存在DOM中,都會先移除,再插入到新位置。
刪除一個元素自身

myElement.parentNode.removeChild(myElement)
// 添加、刪除子元素.屢次appendChild到一個父節點會引發瀏覽器屢次從新渲染,此時能夠將節點組合到fragment = document.createDocumentFragment()中。
ele.appendChild(el);//避免鏈式操做
ele.removeChild(el);//若是有返回值,則存在內存中。

// 替換子元素
//newChild若是存在dom中,則會被移除。replaceNode 爲oldChild
replaceNode = parentNode.replaceChild(newChild, oldChild);

// 插入子元素
//newElement若是存在dom中,會先被移除再插入(不想移除可先複製)。
//referenceElement必須有,可爲null,爲null時,插入到parentElement最後
//return新增長的node(fragment不返回)
newElement = parentElement.insertBefore(newElement, referenceElement);
//沒有insertAfter
parentElement.insertBefore(newElement,referenceElement.nextSibling)
//prepend,使用insertBefore代替。
ParentNode.prepend(nodesToPrepend); //IE支持很差
parentElement.insertBefore(newElement, theFirstChild);//jquery中prepend()也是用此方法


//克隆節點
//node須要被克隆的node
//deep爲ture,則克隆全部子節點。deep不要省略,由於各版本瀏覽器默認值不一樣。
//深度克隆會克隆全部屬性(除addEventListener和後續添加的click事件如:node.onclick = fn,可是會克隆寫在dom中的onclick事件),容易致使id重複的問題。
var dupNode = node.cloneNode([deep]);
//document和iframe之間的克隆
var node = document.importNode(externalNode, deep);

修改class,屬性和樣式


修改屬性

.getAttibute(), .setAttribute()和.removeAttribute()這三個方法。這些方法直接修改的是元素的HTML屬性(與DOM屬性相對),所以會使瀏覽器從新渲染。瀏覽器從新渲染不只比只是設置DOM屬性代價更高,並且還會產生不指望的後果。做爲一個小原則,除非你真的想對HTML「持久化」那些改變,你就只用上面的方法修改與DOM屬性不相關的HTML屬性(好比colspan)

// 獲取一個{name, value}的數組
var attrs = el.attributes;

// 獲取、設置屬性
var c = el.getAttribute('class');
el.setAttribute('class', 'highlight');

// 判斷、移除屬性
el.hasAttribute('class');
el.removeAttribute('class');

// 是否有屬性設置
el.hasAttributes();  

// Get an attribute value
const value = myElement.value

// Set an attribute as an element property
myElement.value = 'foo'

// Set multiple properties using Object.assign()
Object.assign(myElement, {
  value: 'foo',
  id: 'bar'
})

// Remove an attribute
myElement.value = null

修改class


className和classList

myElement.classList.add('foo')
myElement.classList.remove('bar')
myElement.classList.toggle('baz')

el.className += ' class'

修改樣式


在JavaScript裏要寫成駝峯形式.若是咱們想得到CSS規則的值,咱們能夠經過.style屬性。然而,經過它只能拿到咱們明確設置過的樣式。想拿到計算後的樣式值,咱們能夠用.window.getComputedStyle()。它能夠拿到這個元素並返回一個CSSStyleDeclaration。這個返回值包括了這個元素本身的和繼承自父元素的所有樣式。

myElement.style.marginLeft = '2em'
window.getComputedStyle(myElement).getPropertyValue('margin-left')
// 動態添加樣式規則
var style = document.createElement('style');
style.innerHTML = 'body{color:red} #top:hover{background-color: red;color: white;}';
document.head.appendChild(style);

常見問題

  • innerHTML與outerHTML的區別?

    DOM元素的innerHTML, outerHTML, innerText, outerText屬性的區別也常常被面試官問到, 好比對於這樣一個HTML元素:

    <div id="main">
        我是測試文本<br/>
    </div>
    let el = document.querySelector("#main");
    console.log("el.innerHTML: ",el.innerHTML); //我是測試文本<br>
    console.log("el.outerHTML: ",el.outerHTML); //<div id="main">我是測試文本<br></div>
    console.log("el.innerText: ",el.innerText); //我是測試文本
    console.log("el.outerText: ",el.outerText); //我是測試文本
    /* el.innerText = "哈哈"; */
    el.outerText = "哈哈";
    • innerHTML:內部HTML;
    • outerHTML:外部HTML;
    • innerText:內部文本;
    • outerText:內部文本;

上述四個屬性不只能夠讀取,還能夠賦值。outerText和innerText的區別在於outerText賦值時會把標籤一塊兒賦值掉,另外xxText賦值時HTML特殊字符會被轉義。

clipboard.png

https://jsfiddle.net/langlang...

  • jQuery的html()與innerHTML的區別?

    jQuery的.html()會調用.innerHTML來操做,但同時也會catch異常,而後用.empty(), .append()來從新操做。 這是由於IE8中有些元素的.innerHTML是隻讀的。見:http://stackoverflow.com/ques...

  • NodeList 和 HTMLCollection區別
    NodeList是節點集合,包括任何節點類型。HTMLCollection是元素集合。NodeList有.forEach(),但IE不支持,因此通常轉換成數組再調用

    //[Arry.from()][5]
    Array.from(myElements).forEach(doSth);
    Array.protoType.forEach.call(myElements,doSth);
    [].forEach.call(myElements,doSth)

參考文章:

相關文章
相關標籤/搜索