JavaScrip 之 DOM

来源:https://www.cnblogs.com/gaoguowen/archive/2019/12/17/12056235.html
-Advertisement-
Play Games

DOM 樹 HTML 文檔的骨幹是標簽。 根據文檔對象模型(DOM),每個HTML標簽都是一個對象,同樣標簽內的文本也是一個對象。因此這些對象都可通過 JavaScript 操作 如果文檔中有空格(就像任何字元一樣),那麼它們將成為 DOM 中的文本節點,如果我們刪除它們,則不會有任何內容。 `` ...


DOM 樹

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

通常再瀏覽器中的文本不會顯示開頭/結尾的空文本節點,標簽之間也不會顯示空文本節點。

如果瀏覽器遇到格式不正確的HTML,在形成DOM是會自動修複它
如:
<html> 即使不在文檔中,瀏覽器也會自動創建它

按DOM規範,table 必須具有 <tbody>,因此table中未使用<tbody> 形成DOM時會自動添加。

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

遍歷DOM節點

所有對DOM的操作都是從document對象開始,將這個對象賦予一個變數,對其進行修改操作

最頂端的節點

DOM節點樹可以通過 document屬性使用
頂端的節點對應<html> 並且 <html> = document.documentElement
<body> = document.body,<head> = document.head
docment.body可能為null,如果將script腳本放入 <head>標簽種,那麼此腳本無法訪問到document.body,即為null

childNodes

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

parentNOde / siblingNode

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

只訪問元素節點

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

parentElement 可能為null,因為其方法返回的是父元素節點,而parentNode返回的是任何類型的父節點,因此,document.documentElement.parentElement === null

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 (靜態 如果使用迴圈創建查詢的元素,新的元素不會實時加入到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
  }
}

Owen 的個人博客
博客園


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 拖拽 ~~~javascript ~~~ ...
  • Ajax簡介 一門非同步的載入技術,局部刷新 非同步載入,可以在不重載整個網頁的前提下,進行局部刷新 分為原生和JQ兩種 JSON數據格式 Json對象轉字元串: JSON.stringify() 字元串轉Json對象:JSON.parse() 前後端數據交互 html文件 py文件 Ajax局部刷新 ...
  • 事件的傳播 ~~~javascript ~~~ ...
  • 事件的綁定 ~~~javascript btn01 ~~~ ...
  • 在潤乾官方線上 demo的 "交互報表" 中,有介紹 "點擊表頭排序" 的報表案例,該報表針對普通統計類報表。對於使用大數據集的報表,當按照此方式改造時發現排序沒起作用或僅對第一頁或前幾頁排序,後面的都沒成功。 要想瞭解啥原因導致?就需要分析該報表的做法及知道大數據集的取數原理。 首先,來分析下線上 ...
  • 最近在學習react框架,之前一直都是用vue 開發,知道在vue 中知道如何配置一下相關的webpack 有助於開發,學react 過程中,我也在想這些該怎麼配置啊,所以就有這篇文章。 這篇文章主要是講 react-create-app 生成的項目利用 react-app-rewired 和 cu ...
  • 小程式APP生命周期需要先從app.js這個文件開始,App() 必須在 app.js 中調用,必須調用且只能調用一次,app.js中定義了一些應用的生命周期函數 onLaunch 當小程式初始化完成時,會觸發 onLaunch(全局只觸發一次) onShow 當小程式啟動,或從後臺進入前臺顯示,會 ...
  • 之前文章有寫到vue構造函數的實例化過程,只是對vue實例做了個粗略的描述,並沒有說明vue組件實例化的過程。本文主要對vue組件的實例化過程做一些簡要的描述。 組件的實例化與vue構造函數的實例化,大部分是類似的,vue的實例可以當做一個根組件,普通組件的實例化可以當做子組件。真實的DOM是一個樹 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...