JavaScript入門系列目錄
- JavaScript入門①-基礎知識築基
- JavaScript入門②-函式(1)基礎{淺出}
- JavaScript入門③-函式(2)原理{深入}執行上下文
- JavaScript入門④-萬物皆物件:Object
- JavaScript入門⑤-欲罷不能的物件、原型與繼承
- JavaScript入門⑥-WEB瀏覽器API
- JavaScript入門⑦-DOM操作大全
- JavaScript入門⑧-事件總結大全
- JavaScript入門⑨-非同步程式設計●異世界之旅
- JavaScript入門⑩-ES6歸納總結
01、DOM(document)
DOM(Document Object Model)文件物件模型,將文件document
解析為一個由節點和物件(包含屬性和方法的物件)組成的邏輯樹,每個節點都是一個物件,document
物件就是整個DOM樹的根節點。DOM提供的API方法用來管理這棵樹,用JavaScript 等指令碼語言操作文件結構、樣式和內容。
1.1、DOM結構-節點/元素
DOM樹是由很多節點構成,分為下面幾種型別,注意節點是包含文字、註釋的。
節點型別 | 描述 | 示例 |
---|---|---|
document 文件節點 |
document 文件本身,DOM的入口(根) |
document |
element 元素節點 |
所有HTML元素Element /ˈelɪmənt/ i |
html、body、a、p |
attribute 屬性節點 |
元素的屬性 | id、name、href、class |
文字節點 | 元素內的文字形成文字節點 | 文字字元、換行、空格 |
註釋節點 | 註釋 | <!--註釋--> |
一顆完整的DOM樹,除了顯而易見的元素,還有註釋、換行符構成的文字類節點。
<!DOCTYPE HTML>
<html>
<body>
The truth about elk.
<ol>
<li>An elk is a smart</li>
<!-- comment -->
<li>...and cunning animal!</li>
</ol>
</body>
</html>
當前選擇元素
$0
:在瀏覽器控制檯中,$0
標識當前選中的元素。$0.style.background='red';
節點和元素在DOM樹上的不同檢視(導航方式)如下圖,現代JS中主要使用元素導航屬性。
✅節點-導航屬性 | 描述 | ✅元素-導航屬性 | 描述 |
---|---|---|---|
parentNode |
父節點 | parentElement |
父元素,一般和parentNode一樣 ,只有document.documentElement不同 |
firstChild |
第一個子節點 | firstElementChild |
第一個子元素 |
lastChild |
最後一個子節點 | lastElementChild |
最後一個子元素 |
childNodes |
子節點集合 | children |
子元素集合 |
nextSibling |
下一個兄弟節點 | nextElementSibling |
下一個兄弟元素( Sibling/ˈsɪblɪŋ/ 兄弟) |
previousSibling |
上一個兄弟節點 | previousElementSibling |
上一個兄弟元素(/ˈpriːviəs/以前 ) |
document.documentElement.parentNode; //HTMLDocument
document.documentElement.parentElement; //null
document.body.childNodes.length; //33
document.body.children.length; //16
document.body.firstElementChild;
❓元素節點:這裡的導航屬性都是只讀的,不可用於插入、修改元素;都是實時的;集合是可迭代的,用
for..of
,不要用for(in)
1.2、節點Node/元素Element
節點/元素的繼承層次結構如下,最基礎的EventTarget
又繼承自Object
,因此可以自由新增屬性、方法。
- EventTarget:—— 是一切的根(“抽象(abstract)”類),定義了基礎的事件。
- Node:也是一個“抽象”類,充當 DOM 節點的基礎,提供了節點導航功能,如parentNode,nextSibling,childNodes 等。
- Document:表示整個文件,全域性變數
document
就是他。 - CharacterData:一個文字“抽象”類,被Text(文字節點) 、Comment (註釋節點)繼承。(Character/ˈkærəktər/ 符號文字)
- Element:是 DOM 元素的基礎類,提供了元素導航功能,如nextElementSibling,children等,以及搜尋方法
getElementsByTagName
和querySelector
等。 - HTMLElement:所有 HTML 元素的基礎類,常用的如:HTMLInputElement、HTMLBodyElement、HTMLAnchorElement、HTMLDivElement、HTMLTableElement
document.body.querySelector("div").constructor.name; //HTMLDivElement
document.body.querySelector("div").toString(); //[object HTMLDivElement]
?Node節點
Node節點物件的屬性:
Node屬性/方法 | 描述 |
---|---|
data | 文字/註釋節點的文字值,可修改,註釋節點可用來存放一些待處理內容 |
nodeName | 節點名稱 |
textContent | 元素內文字,不含標籤。可修改,可安全的寫入文字。 |
appendChild(node) | 從末尾追加一個子節點 |
removeChild(child) | 刪除一個子節點 |
replaceChild(new,old) | 替換一個子節點 |
insertBefore(new,ref) | 在ref節點前插入一個節點 |
cloneNode(deep) | 克隆當前節點副本,deep=true會克隆其所有後代,否則只是節點本身 |
contains( node) | 是否包含指定的後代節點,返回bool |
hasChildNodes() | 是否包含子節點,返回bool |
// <div id="div">div內容<p>p內容</p></div>
let div = document.querySelector('#div');
console.log(div.innerHTML,div.textContent,div.innerText); //div內容<p>p內容</p> div內容p內容 div內容\n\np內容
console.log(div.nodeName, div.localName, div.tagName); //DIV div DIV
?Element 元素
Element 基類元素物件提供的屬性方法:
✅Element屬性 | 描述 |
---|---|
id | 唯一id ,基礎通用屬性還要name 、class 、style |
localName | 本地化名稱,名稱相關的還有nodeName 、tagName |
classList、className | class樣式集合、class樣式值,集合可以新增、刪除。 |
innerHTML | 元素標籤內的所有HTML內容,可以修改,注意innerHTML+= 會進行完全重寫 |
outerHTML | 包含元素本身及其內部的所有HTML內容,可以修改(刪除並替換) |
innerText | 元素標籤內的所有文字節點值,包含所有後代節點的文字。 |
hidden | 是否隱藏的bool屬性, |
✅方法 | |
addEventListener() | 註冊實踐到EventTarget,還有配套的removeEventListener() |
append(node...) | 在末尾追加多個子節點(或DOMString=text節點) |
prepend(node...) | 在開頭插入多個子節點(或DOMString) |
after(node...) | 在後面插入節點(或DOMString) |
before(node...) | 在前面插入節點(或DOMString) |
replaceWith(node) | 將 node 替換為給定的節點或字串 |
remove(element) | 把物件從它所屬的 DOM 樹中刪除 |
scroll()/scrollBy() | 元素內滾動 |
✅事件(event) | |
blur(event)、focusout() | 元素失去焦點,blur不會冒泡 (blue /blɜːr/ 模糊) |
focus、focusin | 元素獲取焦點時觸發,focus不會冒泡 |
keydown、keyup | 鍵盤按鍵按下、鬆開時觸發 |
click(event) | 點選觸發,通常是滑鼠左鍵在一個元素上被按下並放開時 |
dblclick | 雙擊觸發事件 |
mousedown、mouseup | 滑鼠按下、彈起時觸發 |
mousemove | 滑鼠在元素上移動時觸發 |
onmouseover、mouseout | 滑鼠移入、移出元素區域時觸發 |
mouseenter、mouseleave | 滑鼠移入、移出元素區域時觸發,與上面不同的是不會冒泡 |
<div class="h1 c2" id="firstDiv" myatt="自定義特性" order="asc">Element</div>
<script>
let div = document.querySelector('#firstDiv');
div.classList.add("c5");
div.setAttribute("att2", 3) //新增、設定屬性值
div.addEventListener("click",
(event) => {
console.log(event)
});
div.hidden = true;
</script>
?注意:DOM操作必須等節點初始化完成後才能進行。可以在html尾部執行JS,或者在
window
的onload
事件中處理
1.3、元素特性Attribute
元素特性的操作方法:
Element-特性方法 | |
---|---|
attributes | 所有屬性節點的一個實時集合,支援移除項、屬性值操作,ele.attributes["href"].value |
getAttribute(attName) | 獲取屬性值 |
getAttributeNames() | 所有屬性名陣列 |
setAttribute(attName,value) | 設定屬性值,可以新增自定義特性,常用於設定css |
removeAttribute(attName) | 從指定的元素中刪除一個屬性 |
hasAttribute(attName) | 判斷是否包含指定屬性,返回一個布林值 |
hasAttributes() | 判斷是否包含屬性,返回一個布林值 |
- 特性(attribute)—— 寫在 HTML 中的內容,值都是字串,大小寫不明感。
- 屬性(property)—— DOM 物件中的內容,大小寫敏感。
❗特性attribute與屬性property:元素上的特性
attribute
與屬性property
基本上都是一致相對應的。也有個別例外,如input.value
只能單向從特性attribute
同步到屬性property
。
<style>
span[data-status="success"] {
color: green;
}
span[data-status="failure"] {
color: red;
}
</style>
<div>
<span data-status="success">操作結果</span> <!--自定義特性用來設定元素狀態樣式-->
</div>
<script>
const espan = document.querySelector("span[data-status]");
console.log(espan.attributes); //所有屬性集合
console.log(espan.getAttributeNames()); //['data-status', 'class', 'style']
console.log(espan.hasAttribute("data-status")); //true
//切換樣式
espan.attributes["data-status"].value="failure";
espan.dataset.status="failure";
espan.setAttribute("data-status","failure");
espan.class="success";
</script>
dataset屬性用來存放自定義的非標準特性,自定義的特性都以“data-”開頭,這是專門保留給程式猿門使用的。如“data-status”,透過elem.dataset.status
訪問(屬性上沒有字首date-
)。這樣可以避免HML語言升級後造成的名稱衝突。
1.4、元素的大小位置
Element-大小位置 | 描述 |
---|---|
clientHeight、clientWidth | 元素內部高度、寬度,包括內邊距(不含邊框) |
offsetWidth/offsetHeight | 元素完整的寬度、高度,為元素的完整大小,包括border |
clientTop/Left | 元素邊框寬度,同border寬度 |
offsetLeft/Top | 元素相對於 offsetParent 左上角的 x/y 座標 |
scrollHeight 、scrollWidth | 元素滾動檢視的高度、寬度,包含滑動隱藏部分。 |
scrollLeft/scrollTop | 元素滾出去(隱藏)的部分寬度、高 |
<style>
#sdiv {
border: 5px solid pink;
padding: 5px;
margin: 5px;
width: 200px;
height: 50px;
overflow: auto;
}
</style>
<div id="sdiv">
光圈效應:會導致愛屋及烏的認知偏差,名人效應就是典型的光環效應。與之相反的是音叉效應(惡魔效應)。
</div>
<script>
let sdiv = document.querySelector('#sdiv');
console.log(sdiv.clientWidth, sdiv.clientHeight); //193 60
console.log(sdiv.offsetWidth, sdiv.offsetHeight); //214 70
console.log(sdiv.scrollWidth, sdiv.scrollHeight); //193 115
console.log(sdiv.clientLeft,sdiv.clientHeight); //5 60
console.log(sdiv.offsetLeft,sdiv.offsetTop); //13 261
console.log(sdiv.scrollLeft,sdiv.scrollTop); //0 0
</script>
1.5、document
✅document屬性 | 描述 |
---|---|
documentElement | 對應 <html> 標籤的 頂層節點 |
all、head、body | 所有元素的集合、head節點、body節點 |
images | 所有<image> 圖片元素集合 |
forms | 所有表單元素 <form> 的列表 |
links | 所有超連結的列表 |
scripts | 所有的 <script> 元素 |
✅擴充套件屬性 | 繼承自 HTMLDocument 介面 |
title | 文件標題(瀏覽器頁籤顯示的名稱)來自<title> 標籤,可以動態修改。 |
readyState | document 的載入狀態:loading( 文件正在被載入)、interactive( 文件被全部讀取,/ˌɪntərˈæktɪv/ 互動)、complete(包括資源都已載入完成) |
domain、URL | 網址域名、完整URL地址。還有個location 屬性同window.location |
cookie | 前頁面的Cookie |
defaultView | 當前window的引用,window===document.defaultView; //true |
console.log(document.documentElement.childNodes); //[head, text, body]
console.log(document.documentElement.children); //[head, body]
//京東首頁
console.log(document.all.length, document.images.length, ); //8438 433
console.log(document.links.length, document.scripts.length); //2771 34
console.log(document.title); //京東(JD.COM)-正品低價、品質保障、配送及時、輕鬆購物!
console.log(document.readyState); //complete
console.log(document.domain, document.URL); //www.jd.com https://www.jd.com/
console.log(document.cookie);
console.log(document.defaultView === window); //true
02、查詢DOM元素
查詢元素、節點的相關方法,最常用、好用的就是querySelector(cssSelector)
了,引數就是css選擇器,這個方法設計的不錯?。
屬性/方法 | 描述 |
---|---|
querySelector(css) | 根據選擇器查詢返回第一個元素,selectors同CSS選擇器 |
querySelectorAll(css) | 根據選擇器查詢返回NodeList集合(靜態集合) |
id 全域性變數 |
元素id 作為全域性變數訪問:hid.innerText="33";``window['hid'] 不推薦使用:容易命名衝突,不容易分辨變數來源 |
elem.matches(css) | 判斷是否匹配css選擇器,返回true 、false |
elem.closest(css) | 查詢離元素最近的+css匹配的+祖先(/klosɪst/靠近),包含elem自己 |
document.getElementById(id) | 根據id獲取一個元素,id重複則取第一個 |
document.getElementsByName(name) | 根據name 屬性獲取元素集合(動態),多用於單選框、核取方塊 |
getElementsByClassName(class) | 根據class 屬性值獲取元素集合(動態,會實時更新) |
getElementsByTagName(tag) | 根據元素標籤名元素集合(動態),getElementsByTagName("div") |
//id=sdiv,可以直接使用
console.log(sdiv.matches('.cname')) //false
console.log(sdiv.closest(':not(div)')); //body
document.body.getElementsByTagName("div"); //HTMLCollection
document.body.querySelectorAll("div"); //NodeList
document.body.querySelector("div") === document.body.querySelectorAll("div")[0]; //true
console.log(sdiv.closest(':not(div)')); //body
03、增刪改DOM元素
屬性/方法 | 描述 |
---|---|
createElement(tagName) | 根據標籤名建立節點元素:document.createElement("div") |
createTextNode(text) | 建立一個文字節點。也可用innerText 直接設定文字內容。 |
ele.append(child...) | 在末尾追加多個子節點(或DOMString=text節點) |
ele.prepend(child...) | 在開頭插入多個子節點(或DOMString) |
ele.after(node...) | 在後面插入節點(或DOMString) |
ele.before(node...) | 在前面插入節點(或DOMString) |
ele.replaceWith(node, ... nodes) | 將 ele 替換為給定的節點或字串 |
ele.remove(element) | 把物件從它所屬的 DOM 樹中刪除 |
elem.insertAdjacentHTML(where, html) | 插入html字元,不會影響現有元素,效能比innerHTML 更好! |
node.cloneNode(deep) | 克隆當前節點副本,deep=true會克隆其所有後代,否則只是節點本身 |
ele.innerHTML | 設定標籤HTML內容,也可以達到建立節點內容的目的 |
ele.innerText | 設定標籤文字內容,相容性最好? |
node.textContent | 設定節點文字內容,效果同上 |
?注意:
- 移動插入:所有插入方法,如果插入的是已存在DOM樹上節點,都會自動從舊的位置刪除再插入到新的位置。
- 下拉框
select
的選項option
可以透過其屬性options
新增。obj1.options.add(new Option("abc",3))
let parent = document.createElement("div"); //這兩個命名(parent、child)和window有衝突的,雖然可以用
let child = document.createElement("p");
child.innerText = "p-innertext";
parent.appendChild(child);
parent.append("sam1", "sam2"); //插入多個文字節點
child.replaceWith(document.createElement("span"), "text-"); //替換節點
console.log(parent.outerHTML); //<div><span></span>text-sam1sam2</div>
parent.innerHTML = "<p>ptext</p>";
console.log(parent.outerHTML); //<div><p>ptext</p></div>
parent.innerText = "<p>ptext</p>"; //會被轉義
console.log(parent.outerHTML); //<div><p>ptext</p></div>
sdiv.append(parent);
3.1、遠古的node方法
遠古時期流傳下來的node
提供的插入節點的方法,返回引數都是Node
。和element
方法主要區別是element
的方法引數可多個,方法也更簡潔。
屬性/方法 | 描述 |
---|---|
node.appendChild(child) | 從末尾追加一個子節點,支援字串引數 |
node.insertBefore(new,ref) | 在ref節點前插入一個節點 |
node.replaceChild(new,old) | 替換一個子節點 |
node.removeChild(child) | 刪除一個子節點 |
3.2、insertAdjacentHTML/Text/Element
插入HTML字元、文字、元素節點的通用方法:(adjacent /əˈdʒeɪs(ə)nt/ 相鄰的)。
屬性/方法 | 描述 |
---|---|
elem.insertAdjacentHTML(where, html) | 插入html字元,不會影響現有元素 |
elem.insertAdjacentElement(where, element) | 插入元素 |
elem.insertAdjacentText(where, text) | 插入文字 |
引數where是一個列舉字元,這個誰取的名真頭疼:
- 'beforebegin':元素自身的前面。
- 'afterbegin':插入元素內部的第一個子節點之前。
- 'beforeend':插入元素內部的最後一個子節點之後。
- 'afterend':元素自身的後面。
<div>
<span id="adjacent">div</span>
</div>
<script>
const adiv = document.getElementById("adjacent");
adiv.insertAdjacentHTML("beforebegin", "-beforebegin-");
adiv.insertAdjacentText("afterbegin","-afterbegin-")
adiv.insertAdjacentText("beforeend","-beforeend-")
adiv.insertAdjacentText("afterend","-afterend-")
console.log(adiv.parentElement.innerHTML);
//-beforebegin-<span id="adjacent">-afterbegin-div-beforeend-</span>-afterend-
</script>
3.3、DocumentFragment包裝器
DocumentFragment 是一個特殊的節點,像一個容器,用來附加其他節點,然後傳輸給其他方法使用,當然好像也可以用陣列代替。(Fragment /ˈfræɡmənt/ 片段)
const adiv=document.getElementById("adjacent");
let fram=new DocumentFragment();
fram.append(document.createElement("li"));
fram.append(document.createElement("li"));
adiv.append(fram);
console.log(adiv.outerHTML);
04、DOM樣式管理
屬性/方法 | 描述 |
---|---|
HTMLElement.style | style是一個物件,對應於css中的屬性,屬性是駝峰命名的,注意值帶單位! |
style.cssText | 設定style 樣式字串值,同html 標籤中的style ,注意會覆蓋已有style樣式 |
ele.className | 獲取、設定class樣式值(字串) |
ele.classList | 樣式class 列表,DOMTokenList集合,支援add/remove/toggle方法 |
length、value | 數量,值(同className ) |
contains(css) | 是否包含指定樣式,返回bool |
add(...css) | 新增(多個)樣式 |
remove(...css) | 移除(多個)樣式 |
replace(old, new) | 替換 |
toggle(css) | 不存在就新增,存在就移除(toggle /ˈtɑːɡl/ 切換) |
windwo.getComputedStyle(ele) | 計算/獲取一個元素的已解析(resolved)樣式style 物件(同elem.style ) |
重置style屬性樣式的方式:
- 值置空:
cdiv.style.backgroundColor="";
- 移除屬性值:
cdiv.style.removeProperty("backgroundColor");
<div id="cssDiv" class="c1 c2 c3 c4">css</div>
<script>
const cdiv = document.getElementById("cssDiv");
cdiv.style.backgroundColor = window.prompt("input background color", "red");
cdiv.style.backgroundColor = "";
cdiv.style.removeProperty("backgroundColor");
cdiv.style.lineHeight = "30px"; //注意要帶單位
cdiv.style.cssText = "color:red;font-weight:bold;" //會覆蓋前面的樣式
//計算樣式
const cdstyle = getComputedStyle(cdiv);
console.log(cdiv.className); //c1 c2 c3 c4
console.log(cdiv.classList); //DOMTokenList(4) [ "c1", "c2", "c3", "c4" ]
cdiv.classList.toggle("c1");
cdiv.classList.remove("c1", "c2");
</script>
05、滾動和座標
有效的文件視窗區域高度、寬度,可以使用 document.documentElement
的 clientWidth/clientHeight
,不含捲軸。window.innerWidth/innerHeight 包括了捲軸。
文件完整大小(包含滾動隱藏的部分):documentElement.scrollWidth/scrollHeight,如果內容沒有鋪滿,某些瀏覽器會小於clientWidth/clientHeight。因此獲取完整文件高度,可以取多個值的最大值:
let scrollHeight = Math.max(document.body.scrollHeight, document.documentElement.scrollHeight,
document.body.offsetHeight, document.documentElement.offsetHeight,
document.body.clientHeight, document.documentElement.clientHeight);
?滾動位置:
- window.scrollX/scrollY,一般就用這個就可以了。
- window.pageXOffset /pageYOffset ,是上面的別稱。
- document.documentElement.scrollLeft/scrollTop
?滾動方法:方法更通用,相容性更好。
- window.scrollBy(x,y) ,移動的距離。
- window.scrollTo(pageX,pageY),移動到座標。
- ele.scrollIntoView(top),滾動到元素
ele
可見,引數top為bool,true(元素顯示在頂部)、false(底部)
?禁止滾動:設定css屬性overflow
:document.body.style.overflow = "hidden"
,可用於元素、document。
?座標:clientX/clientY
為相對於視窗的座標,就是能看到的位置。pageX/pageY
為相對於文件的座標,包括滾動隱藏的部分。
?元素座標:
- 相對於視窗的座標:elem.getBoundingClientRect(),返回一個 DOMRect 物件,包含了座標位置寬(x、y、widht、height、top、left)等屬性。
- 相對於文件的座標:elem.getBoundingClientRect() 加上當前頁面滾動
window.scrollX/scrollY
- 獲取指定座標的元素:document.elementFromPoint(x, y),獲取座標 (x, y) 處巢狀最多的元素。
const cele= document.elementFromPoint(window.innerWidth/2,window.innerHeight/2);
cele.style.backgroundColor='red';
cele.scrollIntoView(true);
const rect = sdiv.getBoundingClientRect();
console.log(rect.x, rect.y, rect.left, rect.top); //13 260.875 13 260.875
©️版權申明:版權所有@安木夕,本文內容僅供學習,歡迎指正、交流,轉載請註明出處!原文編輯地址-語雀