JavaScrip 之 DOM

DOM 樹

HTML 文檔的骨幹是標籤。
根據文檔對象模型(DOM),每一個HTML標籤都是一個對象,一樣標籤內的文本也是一個對象。所以這些對象均可經過 JavaScript 操做
若是文檔中有空格(就像任何字符同樣),那麼它們將成爲 DOM 中的文本節點,若是咱們刪除它們,則不會有任何內容。
<head> 以前的空格和換行符被忽略
</body> 以後放置了一些東西,那麼它會自動移動到 body 內部,由於 HTML 規範要求全部內容必須位於 內。因此 後面可能沒有空格。css

一般再瀏覽器中的文本不會顯示開頭/結尾的空文本節點,標籤之間也不會顯示空文本節點。html

若是瀏覽器遇到格式不正確的HTML,在造成DOM是會自動修復它
如:
<html> 即便不在文檔中,瀏覽器也會自動建立它node

按DOM規範,table 必須具備 <tbody>,所以table中未使用<tbody> 造成DOM時會自動添加。數組

其它 節點:
註釋不會以任何方式影響視覺表示,可是必須遵循一條規則 —— 若是HTML中有東西,那麼它必須在DOM樹中。
HTML中全部內容都是DOM的一部分,
註釋是一個節點甚至<!DOCTYPE...>也是一個節
DOM總有12種節點瀏覽器

遍歷DOM節點

全部對DOM的操做都是從document對象開始,將這個對象賦予一個變量,對其進行修改操做app

最頂端的節點

DOM節點樹能夠經過 document屬性使用
頂端的節點對應<html> 而且 <html> = document.documentElement
<body> = document.body,<head> = document.head
docment.body可能爲null,若是將script腳本放入 <head>標籤種,那麼此腳本沒法訪問到document.body,即爲nulldom

childNodes

childNodes 集合提供對全部子節點包括文本節點的訪問,它看起來是一個數字,實際上只是一個可迭代的類數組對象,所以沒有數組的方法
全部的Dom 集合節點都是隻讀的沒法經過賦值來替換對應的節點
除小部分節點,幾乎全部的DOM集合都是實時的,它們反應的是DOM的實時狀態
不要是有 for...in來遍歷DOM集合,此方法會列出其全部的屬性。
注意此屬性只能訪問到當前script腳本以前對應的節點
能夠經過elem.hasChildNodes()來檢測是否含有子節點性能

parentNOde / siblingNode

經過elem.parentNode可訪問當前節點的父節點
經過elem.previousSibling/elem.nextSibling可訪問對應節點的上/下兄弟節點code

只訪問元素節點

  • children: 只獲取類型爲元素節點的子節點
  • firstElementChild,lastElementChild:只獲取第一或最後一個子元素
  • previousElementSibling, nextElementSibling:兄弟元素
  • parentElement:父元素

parentElement 可能爲null,由於其方法返回的是父元素節點,而parentNode返回的是任何類型的父節點,所以,document.documentElement.parentElement === nullhtm

HTMLCollection (動態)

經過元素查找子元素若是子元素是一個集合將返回 HTMLCollection 類數組

let tb = documet.querySelector('table')
let tbs = tb.tBodies  // HTMLCollection [tbody]
let trs =tbs.rows // HTMLCollection [tr,tr,tr,...]
let tr1 = trs[0]
    tr1.sectionRowIndex //0 當前 tr 在集合中的位置
    tr1.rowIndex // 1 當前 tr 在整張表中的 位置
let tds = tr1.cells // HTMLCollection [td,td,td,...]
    td[0].cellIndex //0 當前 td 在父元素 tr節點 中的位置

NodeList (靜態)

經過 document 中的方法 document.querySelectorAllelem.querySelectorAll獲取的元素集合將返回NodeList類數組
getElement* 方法只能經過 document對象調用

let divs = document.querySelectorAll('div') // NodeList(4) [div.Owen, div#modal, div.main, div]
 document.getElementsByTagName('div')//HTMLCollection [div.Owen]

matches

elem.matches(css)會檢測 elem是否匹配到給定的css選擇器,返回 true 或 false

closest

elem.closest(css)此方法會查找css選擇器匹配到的祖先HTML,包括自身,並返回最早找到的元素

contains

elem.catains(dom) 判斷 dom 是否爲 elem 的後代,或等於elem,返回true 或false

節點屬性

全部的節點都繼承自根節點 EventTarget

  • EventTarget:做爲基礎,讓全部DOM 節點都支持事件
  • Node:做爲DOM 節點的基礎,提供DOM樹的核心功能:parentNodenextSiblingpreviousSiblingChildNodes等(只能讀取 getter);文本節點 Text,元素節點Element,註釋節點Comment都繼承自Node
  • Element:作爲DOM 元素的基類。提供元素級導航: nextElementSiblingchildrengetElement*querySelector等等,瀏覽器不只支持HTML,還支持 XML、SVG等,分別對應的基類 HTMLElementXMLElementSVGElement
  • HTMLElement:做爲全部元素的基類,被各類元素繼承
innerHTML 和 outerHTML
  • innerHTML: 獲取或替換當前節點的全部子節點(不包含當前節點)
  • outerHTML: 替換當前節點

文檔片斷 DocumentFragment

用於存儲節點的包裝器,不會再瀏覽器中展現,須要經過插值方法才能展現包裝器裏面的內容

function creatEl(){
let frag = new DocumentFragment();
 for (let i=1;i<4;i++) {
let li = document.createElement('li')
  li.append(i)
  frag.append(li)
}

return frag
}
ul.append(creatEl())

類樣式的修改等操做

elem.className 對應元素的類名,多個類目以空格分隔

ul.className // "class1 class2 ..."

同時還要一個 elem.classList 對象可訪問類名,它以類數組的方式存在,同時具備 add/remove/toggle/contains 等方法

ul.classList //  DOMTokenList(2) ["333", "444", value: "333 444"]
ul.classList.add('class1')
ul.classList.remove('class1')
ul.classList.toggle('class1') // true 新增
ul.classList.toggle('class1') // false 去除
ul.classList.contains('class1') //false 是否包含

一般咱們使用 style.*單獨對樣式屬性進行修改,若是想要對多種樣式進行調整可以使用 cssText此方法會直接替換以前的樣式

ul.style.cssText = `
    color: red ;
    background-color: skyblue;
    width: 20px;
    text-align: center;`

style 屬性僅針對 style 屬性值進行操做,沒法讀取css類中的屬性值

<style>
body {margin:20 auto;}
</style>
<script>
document.body.style.margin // ""
</script>

這時咱們須要使用 getComputedStyle(el,[,pseudo])方法來獲取對應的值
若是不傳參或值無心義,將返回元素全部樣式,其屬性值都爲解析值,如 font-size:1em 最後獲取的可能爲解析後的值"16px"

let res = getComputedStyle(document.body)
res.marginTop // "20px"
res.margin // 谷歌 "20px 0px" 在火狐中爲 ""  所以訪問確切屬性值須使用完整屬性名

獲取元素的尺寸和滾動距離

  • offsetTop/Left: 獲取相對於設置有position屬性爲 absolute relative、fixed 的值或td、th、table、body的元素的距離
  • offsetWidth/Height:獲取外部寬度/高度,包含border,padding,scrollbar (display:none 或自身不在文檔中,其值爲0或null,由此可判斷當前元素是否被隱藏)
  • clientTop/Left:獲取內側與外側的距離(滾動條在左邊時,包含滾動條的寬度)
  • clientWidth/Height:獲取可視區內容的寬高,即不包含滾動條和border
  • scrollWidth/Height:獲取所有內容(包含隱藏部分)的寬高
  • scrollTop/Left: 獲取 元素隱藏部分的上/左距離,包含border,這兩個屬性可修改,其它屬性能只讀取
    HTML 文件裏若是沒有 <!DOCTYPE HTML> 上述的屬性可能會有所不一樣,這不是一個 JavaScript 的問題,但會影響到 JavaScript。

滾動瀏覽器窗口

pageXOffset/pageYOffset: 獲取可視窗口移動的距離 沒法設值

可經過 window.scrollBy, window.scrollTo, elem.scrollIntoView來滾動窗口

  • scrollBy(x,y):滾動頁面至相對於如今位置的(x,y)位置
  • scrollTo(x,y):滾動到頁面相對於文檔左上方的(x,y),位置,相似於 scrollTop/scrollLeft
  • elem.scrollIntoView(truly):若是 truly 爲真則使 當前元素 滾動至窗口頂部,元素頂部與窗口頂部對齊,若是truly 爲false,則當前元素底部與窗口底部對齊。

若是禁止窗口滾動可以使 樣式屬性 overflow 值爲 hidden

座標

getBoundingClientRect()`方法獲取相對於可視窗口的座標對象

其全部屬性都是以可視窗口左端(X)和頂部(Y)爲起點

ul.getBoundingClientRect()
/*

DOMRect {
    bottom: 829.59375  // 元素底部的Y座標
    height: 210  // 元素真實高度
    left: 0 // 元素左邊 X 座標
    right: 1903 // 元素右邊 X 座標
    top: 619.59375 // 元素頂部 Y 座標
    width: 1903 // 元素自身真實寬度即不包含滾動條
    x: 0
    y: 619.59375
}

*/
document.elementFromPoint

document.elementFromPoint(x,y)返回可視窗口座標(x,y),最頂層的元素

let elem = document.elementFromPoint(0,0) // <p>556666</p>

若是x,y不在正常範圍內將返回 null,

相對於文檔座標,JS並未提供原生標準方法,可本身寫一個出來:
function getDomCoords(el){
    let {top,left} = el.getBoundingClientRect()
  return {
    top:top+ window.pageYOffset,
    left:left+window.pageXOffest
  }
}
相關文章
相關標籤/搜索