前端基礎之JavaScriptDOM和BOM

Xiao0101發表於2024-03-21

一、JavaScript的組成

JavaScript的實現包括以下3個部分:

ECMAScript(核心) 描述了JS的語法和基本物件
文件物件模型 (DOM) 處理網頁內容的方法和介面
瀏覽器物件模型(BOM) 與瀏覽器互動的方法和介面
  1. 核心(Core)

    • 核心部分包括語言的基本語法、資料型別、控制結構等。這些是構成 JavaScript 語言的基本要素,如變數、函式、條件語句、迴圈等。
  2. 文件物件模型(DOM,Document Object Model)

    • DOM 是用於訪問和操作網頁內容的 API。它將網頁表示為一個由節點組成的樹形結構,開發人員可以使用 JavaScript 來操作這些節點,實現對網頁的動態修改和互動。
  3. 瀏覽器物件模型(BOM,Browser Object Model)

    • BOM 是用於與瀏覽器互動的 API 集合。它提供了訪問和控制瀏覽器視窗、歷史記錄、定時器、對話方塊等功能,使開發人員能夠實現更復雜的互動體驗。

JavaScript 的這三個部分共同構成了完整的 JavaScript 環境,使開發人員能夠編寫互動性強、動態性高的網頁應用程式。透過核心部分,開發人員可以處理資料和邏輯;透過 DOM,可以操作網頁元素;透過 BOM,可以控制瀏覽器行為。這使得 JavaScript 成為一種強大的客戶端指令碼語言,被廣泛應用於網頁開發中。

瞭解:

  1. DOM 是 W3C 的標準; [所有瀏覽器公共遵守的標準]
  2. BOM 是 各個瀏覽器廠商根據 DOM在各自瀏覽器上的實現;[表現為不同瀏覽器定義有差別,實現方式不同]
  3. window 是 BOM 物件,而非 js 物件;javacsript是透過訪問BOM(Browser Object Model)物件來訪問、控制、修改客戶端(瀏覽器)

二、BOM

1、BOM介紹

BOM:Browser Object Model 是瀏覽器物件模型,瀏覽器物件模型提供了獨立與內容的、可以與瀏覽器視窗進行互動的物件結構,BOM由多個物件構成,其中代表瀏覽器視窗的window物件是BOM的頂層物件,其他物件都是該物件的子物件。

BOM 顧名思義其實就是為了控制瀏覽器的行為而出現的介面。

那瀏覽器可以做什麼呢?比如跳轉到另一個頁面、前進、後退等等,程式還可能需要獲取螢幕的大小之類的引數。
所以 BOM 就是為了解決這些事情出現的介面。比如我們要讓瀏覽器跳轉到另一個頁面,只需要

location.href = "http://www.xxxx.com";

這個 location 就是 BOM 裡的一個物件。

由於BOM的window包含了document,因此可以直接使用window物件的document屬性,透過document屬性就可以訪問、檢索、修改XHTML文件內容與結構。因為document物件又是DOM(Document Object Model)模型的根節點。

image

可以說,BOM包含了DOM(物件),瀏覽器提供出來給予訪問的是BOM物件,從BOM物件再訪問到DOM物件,從而js可以操作瀏覽器以及瀏覽器讀取到的文件。

2、BOM物件

  • window 物件,是 JS 的最頂層物件,其他的 BOM 物件都是 window 物件的屬性;

  • document 物件,文件物件;

  • location 物件,瀏覽器當前URL資訊;

  • navigator 物件,瀏覽器本身資訊;

  • screen 物件,客戶端螢幕資訊;

  • history 物件,瀏覽器訪問歷史資訊;

(1)Window物件

BOM的核心物件是window,它表示瀏覽器的一個例項。在瀏覽器中,window物件有雙重角色,它既是透過javascript訪問瀏覽器視窗的一個介面,又是ECMAScript規定的Global物件。

  • 所有 JavaScript 全域性物件、函式以及變數均自動成為 window 物件的成員。

  • 全域性變數是 window 物件的屬性。

  • 全域性函式是 window 物件的方法。

// 彈框類的方法,前面省略window,不用寫window
alert('提示資訊')
confirm("確認資訊")
prompt("彈出輸入框")

// 定時器相關
setTimeout(函式,時間) 只執行一次
setInterval(函式,時間) 無限執行
clearTimeout/clearInterval(定時器名稱) 清除定時器

// 正常使用
window.close()    // 關閉當前頁面
window.open("url地址",“開啟的方式(可以是_self或_blank)”,“新視窗的大小”)
window.innerHeight;     // 瀏覽器視窗的高度
window.innerWidth;      // 瀏覽器視窗的寬度
window.moveTo(x, y);    // 移動當前視窗
window.resizeTo(width, height);     // 調整當前視窗的尺寸

部分方法詳細說明:

① window.open()

window.open()Window 物件提供的一個方法,用於在瀏覽器中開啟一個新的視窗或標籤頁。這個方法可以接受四個引數,分別是要載入的 URL、視窗的名稱、特性字串和一個布林值指示是否在新視窗中開啟連結。

下面是 window.open() 方法的基本語法:

window.open(url, name, specs, replace);
  • url:要在新視窗中載入的 URL。可以是一個絕對 URL,也可以是一個相對 URL。
  • name:新視窗的名稱。如果指定了相同名稱的視窗,那麼會在該視窗中載入新的內容。
  • specs:一個包含各種特性設定的字串,比如視窗的大小、位置等。這個引數是可選的。
  • replace:一個布林值,指示是否在新視窗中替換歷史記錄。如果設定為 true,則在新視窗中載入頁面時會替換瀏覽器歷史記錄中的當前頁面。

示例:

// 開啟一個新視窗載入指定 URL
window.open('https://www.example.com', '_blank');

// 開啟一個新視窗,指定大小和位置
window.open('https://www.example.com', 'newWindow', 'width=500,height=400,left=100,top=100');

// 開啟一個新視窗並替換歷史記錄
window.open('https://www.example.com', 'newWindow', '', true);

需要注意的是,使用 window.open() 方法開啟新視窗時,瀏覽器通常會阻止彈出視窗,除非是在使用者互動(比如點選按鈕)的情況下。因此,建議在使用者操作觸發的事件中使用 window.open() 方法,以避免被瀏覽器攔截。

② setTimeout()

setTimeout() 是 JavaScript 中的一個函式,用於在指定的延遲時間後執行一次指定的函式或指定的程式碼。

基本語法如下:

setTimeout(function, delay, param1, param2, ...);
  • function:要執行的函式或要執行的程式碼塊。
  • delay:延遲的時間,以毫秒為單位。
  • param1, param2, ...:可選引數,傳遞給函式的引數(如果有的話)。

示例:

// 在延遲 2000 毫秒(即 2 秒)後執行一個函式
setTimeout(function() {
    console.log('這是一個延遲執行的函式。');
}, 2000);

在上面的示例中,setTimeout() 函式會在 2 秒後執行一個匿名函式,該函式會在控制檯列印出一條訊息。

需要注意的是,setTimeout() 方法並不是精確的定時器,它只能保證在指定的延遲時間後儘快執行指定的函式或程式碼塊。如果在延遲時間到達前 JavaScript 執行緒被佔用,那麼函式執行可能會延遲。

如果需要重複執行一個函式,可以使用 setInterval() 方法,它和 setTimeout() 類似,但會在每個指定的時間間隔重複執行函式。

(2)location物件

location 物件用於獲取或設定視窗的URL,並且提供了與URL相關的資訊。

在瀏覽器的 JavaScript 環境中,location 物件是 Window 物件的一個屬性,可以透過 window.location 或者直接使用 location 訪問。

location物件包含了很多屬性,其中一些常用的屬性包括:

  • location.href: 返回當前頁面的完整 URL。
  • location.href = url : 跳轉到指定的url。
  • location.reload: 重新整理頁面,瀏覽器左上方那個的小圓圈.
  • location.protocol: 返回頁面使用的協議(如 "http:" 或 "https:")。
  • location.host: 返回伺服器名稱和埠號。
  • location.hostname: 返回伺服器名稱。
  • location.port: 返回埠號,如URL中不包含埠號返回空字串。
  • location.pathname: 返回 URL 的路徑部分。 /project/test.html
  • location.search: 返回 URL 的查詢部分(即問號後面的部分)。
  • location.hash: 返回 URL 的片段識別符號(即#號後面的部分)不包含雜湊,則返回空字串。。

透過 location 物件,你可以讀取當前頁面的 URL 資訊,也可以透過修改 location 物件的屬性來改變當前頁面的 URL,實現頁面的重定向或重新整理等操作。但需要注意的是,直接修改 location 物件可能會導致頁面的跳轉,因此在使用時需要謹慎操作。

(3)navigator物件

navigator 物件提供了關於瀏覽器的資訊,可以用來檢測瀏覽器的型別、版本、作業系統等資訊。

在瀏覽器環境中,navigator 物件是 Window 物件的一個屬性,可以透過 window.navigator 或者直接使用 navigator 訪問。

navigator物件包含了很多屬性,其中一些常用的屬性包括:

  • navigator.userAgent: 返回包含使用者代理字串的完整資訊,可以用來識別瀏覽器和作業系統===瀏覽器設定的User-Agent字串。
  • navigator.platform: 返回瀏覽器所在的作業系統型別。
  • navigator.language: 返回瀏覽器當前使用的語言。
  • navigator.cookieEnabled: 返回瀏覽器是否啟用了 cookie。
  • navigator.onLine: 返回瀏覽器是否處於線上狀態。
  • navigator.appName: 返回瀏覽器名稱;
  • navigator.appVersion: 返回瀏覽器版本;
  • userAgent是最常用的屬性,用來表示當前是否是個瀏覽器。

透過 navigator 物件,你可以根據瀏覽器的資訊來進行相應的操作,比如根據使用者代理字串來做瀏覽器相容性處理,或者根據語言設定來展示不同的內容。

需要注意的是,由於使用者代理字串可以被修改,因此在使用 navigator.userAgent 時要謹慎處理,以確保資訊的準確性。

(4)screen物件

screen 物件提供了關於使用者螢幕的資訊,可以用來獲取螢幕的尺寸、顏色深度等相關資訊。在瀏覽器環境中,screen 物件是 Window 物件的一個屬性,可以透過 window.screen 或者直接使用 screen 訪問。

screen 物件包含了一些常用的屬性,其中一些包括:

  • screen.width: 返回螢幕的寬度(以畫素為單位)。
  • screen.height: 返回螢幕的高度(以畫素為單位)。
  • screen.availWidth: 返回螢幕可用的寬度,即去除作業系統工作列等佔用的部分後的寬度。
  • screen.availHeight: 返回螢幕可用的高度,即去除作業系統工作列等佔用的部分後的高度。
  • screen.colorDepth: 返回螢幕的顏色深度,即每個畫素的位數。
  • screen.pixelDepth: 返回螢幕的畫素深度,通常與 screen.colorDepth 相同。

透過 screen 物件,你可以根據使用者的螢幕資訊來進行相應的顯示最佳化,比如根據螢幕尺寸調整頁面佈局,或者根據顏色深度選擇合適的圖片格式以提高效能。這些資訊可以幫助你設計響應式的網頁,以適應不同螢幕尺寸和裝置。

(5)history物件

history 物件在瀏覽器的 JavaScript 環境中提供了訪問瀏覽器歷史記錄的能力。透過 history 物件,你可以在瀏覽器的歷史記錄中向前或向後導航,以及獲取當前瀏覽歷史記錄的狀態資訊。

history 物件包含了一些常用的方法和屬性,其中一些包括:

  • history.length: 返回瀏覽器歷史記錄中的頁面數量。
  • history.back(): 與使用者點選瀏覽器的後退按鈕效果相同,導航到瀏覽器歷史記錄中的前一個頁面。
  • history.forward(): 與使用者點選瀏覽器的前進按鈕效果相同,導航到瀏覽器歷史記錄中的下一個頁面。
  • history.go(i): 導航到瀏覽器歷史記錄中的指定頁面,可以接受一個整數引數i,i>0向前進,i<0往後退。

透過 history 物件,你可以實現一些瀏覽器歷史記錄相關的功能,比如建立自定義的導航按鈕,實現頁面間的跳轉,或者根據使用者的操作記錄實現特定的功能。請注意,由於安全原因,瀏覽器限制了對瀏覽歷史記錄的訪問,使得在某些情況下,部分方法可能無法正常工作。

(6)計時器相關

既可以放在 body 內 又可以放在 head 內

毫秒為單位

  • 計時器在網頁開發中經常用於實現定時觸發某些操作的功能。
  • 根據需求,可以使用不同的方法來觸發定時器。

① 過一段時間觸發(setTimeout):

  • 如果需要在經過一定的時間後觸發某個操作
    • 可以使用setTimeout函式來設定定時器。
  • 示例程式碼:
setTimeout(function() {
  // 在延遲後執行的操作
}, 5000); // 延遲5秒後執行
function foo() {
  // 在延遲後執行的操作
}

setTimeout(foo, 5000); // 延遲5秒後執行
  • 上述程式碼將在5秒鐘後執行指定的函式。可以根據實際需要調整延遲的時間。

② 每隔一段時間觸發一次(setInterval)

  • 如果需要每隔一定的時間重複觸發某個操作
    • 可以使用setInterval函式來設定定時器。
  • 示例程式碼:
setInterval(function() {
  // 每隔一段時間執行的操作
}, 2000); // 每2秒鐘執行一次
function bar() {
  // 每隔一段時間執行的操作
}

setInterval(bar, 2000); // 每2秒鐘執行一次
  • 上述程式碼將每隔2秒鐘執行一次指定的函式。同樣,可以根據實際需要調整時間間隔。

③ 清除定時器(clearTimeout/clearInterval)

clearTimeout

  • clearTimeout函式用於取消使用setTimeout函式設定的定時器。
    • 透過傳遞setTimeout函式返回的計時器識別符號作為引數,可以停止相應的定時器。
    • 如果沒有及時呼叫clearTimeout取消定時器,定時器會按照預定的時間觸發,造成不必要的操作。
  • 示例程式碼:
var timer = setTimeout(function() {
  // 在延遲後執行的操作
}, 5000); // 延遲5秒後執行

// 如果需要取消定時器
clearTimeout(timer);

clearInterval

  • clearInterval函式用於取消使用setInterval函式設定的定時器。
    • 透過傳遞setInterval函式返回的計時器識別符號作為引數,可以停止相應的定時器。
    • 類似地,未及時呼叫clearInterval會導致定時器一直重複執行。
  • 示例程式碼:
var timer = setInterval(function() {
  // 每隔一段時間執行的操作
}, 2000); // 每2秒鐘執行一次

// 如果需要取消定時器
clearInterval(timer);

注意,在呼叫clearTimeout或clearInterval函式時

需要將原先儲存的計時器識別符號作為引數傳遞給這兩個函式,以確保取消正確的定時器。

案例

function func2() {
        alert("123")
    }

    function show() {
        let t = setInterval(func2, 3000); // 每隔3s觸發一次

        function inner() {
            clearInterval(t) // 清除定時器
        }
        
        setTimeout(inner, 9000) // 9s後觸發
    }

    show()
  • 給定的程式碼是用JavaScript編寫的,定義了兩個函式:

    • func2show
  • func2 函式簡單地顯示一個帶有訊息 "123" 的彈窗。

  • show 函式稍微複雜一些。

    • 它首先定義一個變數 t,並將其賦值為 setInterval 函式的返回值。
    • setInterval 函式設定了一個每300毫秒(或3秒)呼叫一次 func2 函式的定時器。
  • 接下來,show 函式定義了一個名為 inner 的內部函式。

    • 這個內部函式用於使用 clearInterval 函式清除之前定義的定時器。
    • clearInterval 函式停止了 func2 函式的重複呼叫。
  • 最後,show 函式使用 setTimeout 函式計劃在900毫秒(或9秒)之後執行 inner 函式。

    • 這意味著,在9秒後,inner 函式將被呼叫,並透過清除定時器來停止 func2 函式的重複執行。
  • 總結一下,show 函式設定了一個定時器,每3秒呼叫一次 func2 函式,但在9秒後,該定時器被清除,阻止了 func2 函式的進一步執行。

④ 注意:

  • 確保清除定時器

    • 如果不再需要定時器,應當及時清除,以避免資源浪費。

    • 可以使用clearTimeout或clearInterval函式來取消定時器。

  • 考慮瀏覽器相容性

    • 在使用定時器時,應注意不同瀏覽器對定時器的支援可能存在差異,可以使用各種前端框架或庫提供的方法來處理相容性問題。
  • 注意定時器的效能影響

    • 頻繁的定時器操作可能會對網頁效能產生一定影響,特別是在移動裝置上,所以應慎重使用大量的定時器。

三、DOM

1、DOM介紹

DOM(Document Object Model),也就是文件物件模型。是針對XML的基於樹的API。描述了處理網頁內容的方法和介面,是HTML和XML的API,DOM把整個頁面規劃成由節點層級構成的文件。

這個DOM定義了一個HTMLDocument和HTMLElement做為這種實現的基礎,就是說為了能以程式設計的方法操作這個 HTML 的內容(比如新增某些元素、修改元素的內容、刪除某些元素),我們把這個 HTML 看做一個物件樹(DOM樹),它本身和裡面的所有東西比如<div></div>這些標籤都看做一個物件,每個物件都叫做一個節點(node),節點可以理解為 DOM 中所有 Object 的父類。

image

DOM模型將整個文件(XML文件和HTML文件)看成一個樹形結構,

在DOM中,HTML文件的層次結構被表示為一個樹形結構。並用document物件表示該文件,樹的每個子節點表示HTML文件中的不同內容。

每個載入瀏覽器的 HTML 文件都會成為 Document 物件,Document是探索DOM的入口,利用全域性變數document可以訪問Document物件。

ps: DOM 有什麼用?

就是為了操作 HTML 中的元素,比如說我們要透過 JS 把這個網頁的標題改了,直接這樣就可以了:

document.title = 'how to make cakes';

這個 API 使得在網頁被下載到瀏覽器之後改變網頁的內容成為可能。

  • DOM操作需要用關鍵字document起手

2、DOM操作

(1)查詢標籤

在 JavaScript 中,透過 DOM(文件物件模型)可以對網頁上的元素進行訪問和操作。查詢標籤是 DOM 操作中常見的任務之一,常用的方法可以分為三種:

  • 直接查詢
  • 半間接查詢
  • 間接查詢

① 直接查詢

  1. getElementById():
    • 透過元素的 id 屬性來獲取元素。每個頁面中的元素 id 應該是唯一的。
    • 示例:document.getElementById('myElementId')
// 使用元素的唯一ID來獲取元素
HTML: 
	<div id="myDiv">Hello World</div>
var divEle = document.getElementById('myDiv');
  1. getElementsByClassName():

    • 透過元素的類名來獲取元素。返回一個包含所有指定類名的元素列表。

    • 示例:document.getElementsByClassName('myClassName')

// 透過類名獲取元素
HTML: 
	<p class="myClass">Paragraph 1</p>
	<p class="myClass">Paragraph 2</p>
var pEle = document.getElementsByClassName('myClass');
  1. getElementsByTagName():

    • 透過元素的標籤名來獲取元素。返回一個包含所有指定標籤名的元素列表。

    • 示例:document.getElementsByTagName('div')

// 透過標籤名獲取元素
HTML:
	<ul>
    	<li>Item 1</li>
		<li>Item 2</li>
	</ul>
var liEle = document.getElementsByTagName('li');

當我們在用變數名指代標籤物件時,一般都建議寫成

xxxEle

​ divEle

​ aEle

​ pEle

  • 這些方法可以根據不同的需求和條件進行標籤查詢。

    • 使用getElementById適合於查詢單個具有唯一ID的元素

    • getElementsByTagName和getElementsByClassName適合於查詢多個相同標籤名稱或類名的元素。

需要注意的是,以上方法返回的是一個HTML元素或HTML元素列表(NodeList)

② 半間接查詢

  1. querySelector():
  • 使用 CSS 選擇器來查詢匹配的第一個元素。
  • 示例:document.querySelector('#myElementId .myClassName')
// 使用 CSS 選擇器查詢匹配的第一個元素
HTML: 
	<div id="container">
    	<p class="text">Some text</p>
	</div>
var element = document.querySelector('#container .text');
  1. querySelectorAll():
  • 使用 CSS 選擇器來查詢匹配的所有元素,返回一個 NodeList 物件。
  • 示例:document.querySelectorAll('.myClassName')
// 使用 CSS 選擇器查詢匹配的所有元素
HTML:
	<ul>
    	<li>Item 1</li>
		<li>Item 2</li>
	</ul>
var listItems = document.querySelectorAll('ul li');

選擇器可以是標籤名稱、類名、ID、屬性等,更復雜的選擇器甚至可以選擇巢狀結構。

透過選擇器查詢,您可以更靈活地查詢和操作HTML元素。

③ 間接查詢

  1. parentNode:
    • 透過父節點來查詢子節點。
    • 示例:myElement.parentNode
// 透過父節點查詢子節點
HTML: 
	<div id="parent">
    	<p>Child element</p>
	</div>
var parentElement = document.getElementById('parent');
var childElement = parentElement.children[0];
  1. children:

    • 獲取元素的所有子元素。

    • 示例:myElement.children

// 獲取所有子元素
HTML: 
	<ul>
        <li>Item 1</li>
		<li>Item 2</li>
	</ul>
var list = document.getElementsByTagName('ul')[0];
var childElements = list.children;
  1. nextSiblingpreviousSibling:

    • 獲取相鄰的下一個兄弟節點和上一個兄弟節點。

    • 示例:myElement.nextSiblingmyElement.previousSibling

// 獲取相鄰的下一個兄弟節點和上一個兄弟節點
HTML: 
	<ul>
    	<li>Item 1</li>
		<li>Item 2</li>
	</ul>
var firstItem = document.getElementsByTagName('li')[0];
var nextItem = firstItem.nextSibling;
var prevItem = nextItem.previousSibling;
  1. firstElementChild:
    • firstElementChild屬性指向指定元素的第一個子元素。
    • 它類似於children屬性,但它只返回第一個子元素,忽略在它之前存在的任何非元素節點。
    • 例如,element.firstElementChild將返回指定元素的第一個子元素。
// 取第一個子標籤
divEle.firstElementChild
// <div>​ 第一個div 內的 第一個 div [div>div]​</div>​
  1. lastElementChild:

    • 類似於firstElementChild,lastElementChild屬性指向指定元素的最後一個子元素。

    • 它僅包括最後一個元素作為其子節點,忽略在它之後的任何非元素節點。

    • 例如,element.lastElementChild將返回指定元素的最後一個子元素。

// 取最後一個子標籤
divEle.lastElementChild
// <p>​ 第一個div 內的 第二個 p [div>p] ​</p>​

這些方法和屬性可以幫助你在 DOM 中查詢特定的元素,從而進行進一步的操作和處理。在實際開發中,根據具體的需求和場景選擇合適的方法來查詢和操作元素是非常重要的。

(2)節點操作

在DOM操作中,節點操作是非常常見和重要的部分。DOM透過建立樹來表示文件,描述了處理網頁內容的方法和介面,從而使開發者對文件的內容和結構具有空前的控制力,用DOM API可以輕鬆地刪除、新增和替換節點。

型別 描述
元素節點(Element) 上圖中<html><body><p>等都是元素節點,即標籤。
文字節點(Text) 向使用者展示的內容,如<li>...</li>中的 JavaScript、DOM、CSS等文字。
屬性節點(Attr) 元素屬性,元素才有屬性,如<a>標籤的連結屬性href="http://www.baidu.com"。

以下是一些常用的節點操作以及相應的程式碼解釋:

  1. 建立新節點
    • 透過document物件的createElement(eleName)、createTextNode(nodeValue)方法可分別建立元素節點和文字節點。屬性節點也有自己的create方法,但是用的少,直接用元素節點的setAttribute()方法即可新增屬性。
// 建立一個新的 <div> 元素
var newDiv = document.createElement('div');
// 建立一個新的文字節點
var newText = document.createTextNode("New Text Created!");
  1. 插入節點

    • 兩個重要的方法:appendChild() 和 insertBefore(),具體見Node介面中的方法。

    • 擴充套件:上面的兩個方法都是在已知父節點時用到的,也可以直接在兄弟節點後新增新節點:x.insertBefore(newNode) 和 x.appendChild(newNode) 都可以向 x 後追加一個新的子節點。

// 將新建立的 <div> 元素插入到 id 為 "container" 的元素中
var container = document.getElementById('container');
container.appendChild(newDiv);
// 獲取要操作的元素
var myDiv = document.getElementById("myDiv");
// 建立一個新的段落元素
var newParagraph = document.createElement("p");
newParagraph.textContent = "New Paragraph Inserted!";
// 獲取參考節點(第一個段落)
var referenceNode = myDiv.getElementsByTagName("p")[0];
// 在參考節點前插入新段落
myDiv.insertBefore(newParagraph, referenceNode);
  1. 刪除節點
    • 刪除元素節點: 使用 parentNode.removeChild() 刪除一個子節點。
    • 刪除屬性節點:可透過屬性節點所屬的元素節點的removeAttribute(attrName)或removeAttributeNode(node)刪除。
    • 清空文字節點:最簡單也是最常用的方法就是直接設定文字節點的nameNode屬性為空串:textNode.nodeValue = ””。
// 刪除 id 為 "myDiv" 的元素
var elementToRemove = document.getElementById('myDiv');
elementToRemove.parentNode.removeChild(elementToRemove);

 var myDiv = document.getElementById("myDiv");
// 移除 class 屬性
myDiv.removeAttribute("class");

// 建立一個新的屬性節點
var customAttr = document.createAttribute("data-custom");
customAttr.value = "example";
// 移除自定義屬性節點
myDiv.removeAttributeNode(customAttr);
  1. 替換節點
    • 使用 parentNode.replaceChild() 替換一個子節點。
// 替換 id 為 "oldDiv" 的元素為新建立的 <div> 元素
var oldDiv = document.getElementById('oldDiv');
oldDiv.parentNode.replaceChild(newDiv, oldDiv);
  1. 複製節點
    • 使用 node.cloneNode() 複製一個節點。
// 複製 id 為 "myDiv" 的元素
var originalElement = document.getElementById('myDiv');
var clonedElement = originalElement.cloneNode(true); // 引數為 true 表示深度複製
  1. 設定/獲取節點的屬性

    • 使用 element.setAttribute() 設定節點的屬性,

    • 使用 element.getAttribute() 獲取節點的屬性。

// 設定 id 為 "myElement" 的元素的 class 屬性為 "newClass"
var element = document.getElementById('myElement');
element.setAttribute('class', 'newClass');

// 獲取 id 為 "myElement" 的元素的 class 屬性值
var elementClass = element.getAttribute('class');

- getElementById(id): 根據元素的id屬性獲取對應的元素節點。
- getElementsByTagName(tagName): 根據元素的標籤名獲取一組元素節點。
- getElementsByClassName(className): 根據元素的類名獲取一組元素節點。
- querySelector(selector): 使用CSS選擇器獲取匹配的第一個元素節點。
- querySelectorAll(selector): 使用CSS選擇器獲取匹配的所有元素節點。
  1. 修改節點內容(文字操作)

    • 使用 element.innerHTML 修改節點的 HTML 內容,

    • 使用 element.textContent 修改節點的文字內容。

// 修改 id 為 "myElement" 的元素的 HTML 內容
var element = document.getElementById('myElement');
element.innerHTML = '<p>New content</p>';

// 修改 id 為 "myElement" 的元素的文字內容
element.textContent = 'New text content';

這些節點操作方法可以幫助您在JavaScript中對DOM進行更靈活的操作,從而實現動態的頁面互動和內容更新。

案例使用:

  • 透過DOM操作動態的建立img標籤
  • 並且給標籤加屬性
  • 最後將標籤新增到文字中

這個操作只是作用域當前頁面,並沒有對原始檔案生效

重新整理後就會消失相關的效果

let imgEle = document.createElement('img')  #建立標籤
imgEle.src = '1.png'  # 給標籤設定預設的屬性
// '1.png'
imgEle.username = 'xiao'  # 自定義的屬性沒辦法點的方式直接設定
// 'xiao'
imgEle.setAttribute('username','xiao') # 既可以設定自定義的屬性也可以設定預設的書寫
imgEle
// <img src=​"1.png" username=​"xiao">​
imgEle.setAttribute('title','一張圖片')
imgEle
// <img src=​"1.png" username=​"xiao" title=​"一張圖片">​
let divEle = document.getElementById('d1')
divEle.appendChild(imgEle)  # 標籤內部新增元素(尾部新增)
// <img src=​"1.png" username=​"xiao" title=​"一張圖片">​

  • 建立a標籤
  • 設定屬性,設定文字
  • 新增到標籤內部並新增到指定的標籤上面
let aEle = document.createElement('a')
aEle
// <a>​</a>​
aEle.href = 'https://www.baidu.com/'
// 'https://www.baidu.com/'
aEle
// <a href=​"https:​/​/​www.baidu.com/​">​</a>​
aEle.innerText = '大爺快來玩啊'  # 給標籤設定文字內容
// '大爺快來玩啊'
aEle
// <a href=​"https:​/​/​www.baidu.com/​">​大爺快來玩啊​</a>​
let divEle = document.getElementById('d1')
let pEle = document.getElementById('d2')
divEle.insertBefore(aEle,pEle)  # 新增標籤內容指定位置新增
// <a href=​"https:​/​/​www.baidu.com/​">​大爺快來玩啊​</a>​

(3)補充:innerText/innerHTML

// 只拿標籤內的文字 -- 不識別 html標籤
divEle.innerText
// 'div 點我有你好看\n\ndiv > p\n\ndiv > span'

// 拿標籤內的全部內容和標籤 -- 識別 html標籤
divEle.innerHTML
/* ' div\n    <a href="https://www.mzitu.com/">點我有你好看</a><p id="p1"> div &gt; p</p>\n    <span> div &gt; span </span>\n' */ 

innerText和innerHTML是用於在網頁中更新文字內容的兩種方法。

它們都可以用於修改HTML元素中的文字,但有一些關鍵的區別。

① innerText

  • innerText屬性用於設定或返回指定元素中的文字內容,不包括HTML標記。

  • 當使用innerText屬性時,所有HTML標記都將被視為純文字並被直接顯示在頁面上。

  • 這意味著如果在innerText中包含HTML標記,那麼標記將被作為普通文字顯示而不會被解析。

  • 此外,innerText屬性是隻讀的,即使嘗試修改該屬性的值也不會有任何效果。

使用示例:

<div id="myElement">This is <strong>bold</strong> text.</div>
<script>
   var element = document.getElementById("myElement");
   console.log(element.innerText); // 輸出:"This is bold text."
   element.innerText = "Updated text"; // 嘗試修改innerText但不會生效
</script>

② innerHTML

  • innerHTML屬性用於設定或返回指定元素的HTML內容,可以包含HTML標記和文字。
  • 與innerText不同,使用innerHTML屬性時,所有HTML標記都會被解析並在頁面上正確渲染。
    • 這意味著可以透過innerHTML屬性來新增、修改或刪除HTML元素及其屬性。
  • 需要注意的是,innerHTML屬性可以導致程式碼注入攻擊,因此使用時需謹慎驗證並過濾使用者輸入。

使用示例:

<div id="myElement">This is <strong>bold</strong> text.</div>
<script>
   var element = document.getElementById("myElement");
   console.log(element.innerHTML); // 輸出:"This is <strong>bold</strong> text."
   element.innerHTML = "Updated <em>text</em>"; // 修改innerHTML會動態更新頁面中的內容
</script>

③ 總結

  • innerText用於操作元素中的純文字內容,不解析HTML標記,且是隻讀屬性。
  • innerHTML用於操作元素中的HTML內容,可以包含HTML標記

(4)獲取值操作

① 獲取屬性值

  • 可以使用getAttribute()方法來獲取HTML元素的屬性值。
  • 該方法需要傳入屬性名作為引數,並返回屬性對應的值。
<div id="myDiv" class="myClass" data-custom="example">Hello, World!</div>
<button onclick="getAttributeValue()">Get Attribute Value</button>

<script>
function getAttributeValue() {
    var divElement = document.getElementById("myDiv");
    
    var classValue = divElement.getAttribute("class");
    console.log("Class Attribute Value: " + classValue);
    
    var customValue = divElement.getAttribute("data-custom");
    console.log("Custom Attribute Value: " + customValue);
}
</script>

在這個示例中,我們有一個 <div> 元素,具有 class 屬性和自定義屬性 data-custom。點選按鈕時,getAttributeValue() 函式會獲取這個元素的 classdata-custom 屬性值,並將它們列印到控制檯。

② 獲取元素的文字內容

  • 可以使用innerTextinnerHTMLtextContent屬性來獲取一個元素的文字內容。

  • 這些屬性會返回元素內包含的文字,但存在一些差異:

  • innerText:返回元素的純文字內容,不包括HTML標記。

  • innerHTML:返回元素的HTML內容,包括HTML標記。

  • textContent:返回元素及其所有子元素的文字內容,包括隱藏元素和註釋等。

<div id="myDiv">Hello, World!</div>
<button onclick="getTextContent()">Get Text Content</button>

<script>
function getTextContent() {
    var divElement = document.getElementById("myDiv");
    var textContent = divElement.textContent;
    console.log("Text Content: " + textContent);
}
</script>

在這個示例中,我們有一個 <div> 元素包含文字內容 "Hello, World!"。點選按鈕時,getTextContent() 函式會獲取這個 <div> 元素的文字內容,並將其列印到控制檯。

③ 獲取表單元素的值

  • 對於表單元素(如input、select、textarea等)
  • 可以透過獲取其value屬性來獲取使用者輸入的值。
<form id="myForm">
    <input type="text" id="myInput" value="Hello, World!">
    <button onclick="getValue()">Get Value</button>
</form>

<script>
function getValue() {
    var inputElement = document.getElementById("myInput");
    var value = inputElement.value;
    console.log("Input Value: " + value);
}
</script>

在這個示例中,我們有一個包含一個文字輸入框和一個按鈕的表單。當點選按鈕時,getValue() 函式會獲取文字輸入框的值,並將其列印到控制檯。

④ 獲取檔案

  • 當使用者選擇一個或多個檔案後
    • 可以透過訪問.files屬性來獲取這些檔案的資訊。
  • .files屬性返回一個FileList物件
    • 其中包含了所選檔案的列表。
    • 可以透過遍歷該列表來處理每個檔案。
  • 以下是一個簡單的示例,演示如何使用.files屬性獲取使用者選擇的檔案:
// 獲取檔案選擇框的DOM元素
var fileInput = document.getElementById("fileInput");

// 新增change事件監聽器,以便在使用者選擇檔案後執行操作
fileInput.addEventListener("change", function() {
  // 獲取選擇的所有檔案
  var files = fileInput.files;

  // 遍歷檔案列表,並處理每個檔案
  for (var i = ; i < files.length; i++) {
    var file = files[i];
    console.log("檔名:" + file.name);
    console.log("檔案型別:" + file.type);
    console.log("檔案大小(位元組):" + file.size);
    console.log("最後修改時間:" + file.lastModified);
  }
});
  • 在以上示例中,我們首先獲取具有id="fileInput"的檔案選擇框的DOM元素,併為其新增了一個change事件監聽器。
    • 當使用者選擇檔案後,change事件將被觸發。
  • 在事件處理程式中,我們使用.files屬性獲取選擇的檔案列表,並遍歷該列表。
    • 對於每個檔案,我們輸出了一些基本資訊,如檔名、檔案型別、檔案大小和最後修改時間。

需要注意的是,.files屬性在非IE瀏覽器中提供了廣泛的支援

但在IE瀏覽器中需要使用.value屬性來獲取檔案路徑並進行相關處理。

(5) class屬性操作

在JavaScript中,您可以使用DOM操作來管理元素的class屬性,這些方法既適用於類名,也適用於類屬性。

let divEle = document.getElementById('d1')
divEle.classList  // 獲取標籤所有的類屬性

以下是一些常見的方法和示例程式碼:

① 新增類名(classList.add()):

您可以使用classList.add()方法向元素新增一個類名。

// 獲取元素
var element = document.getElementById('myElement');

// 新增類名
element.classList.add('newClass');

② 移除類名(classList.remove()):

您可以使用classList.remove()方法從元素中移除一個類名。

// 獲取元素
var element = document.getElementById('myElement');

// 移除類名
element.classList.remove('oldClass');

③ 切換類名(classList.toggle()):

您可以使用classList.toggle()方法來切換一個類名的存在狀態。如果類名存在,則移除它;如果不存在,則新增它。

// 獲取元素
var element = document.getElementById('myElement');

// 切換類名
element.classList.toggle('active');

④ 檢查是否包含某個類名(classList.contains()):

您可以使用classList.contains()方法檢查一個元素是否包含特定的類名。

// 獲取元素
var element = document.getElementById('myElement');

// 檢查是否包含類名
if (element.classList.contains('myClass')) {
    // 包含類名的操作
}

⑤ 替換類名(classList.replace()):

您可以使用classList.replace()方法替換元素的一個類名。

// 獲取元素
var element = document.getElementById('myElement');

// 替換類名
element.classList.replace('oldClass', 'newClass');

這些方法可以幫助您在JavaScript中操作DOM元素的類名,從而實現動態樣式變化和互動效果。

(6)標籤樣式

在JavaScript中,您可以透過DOM操作來改變元素的樣式。

DOM操作操作標籤樣式,統一先用style起手,沒有下劃線,全由駝峰體替代。

以下是一些常見的方法和示例程式碼:

① 直接修改樣式屬性(直接設定元素的樣式屬性):

您可以直接訪問元素的style屬性,並設定其中的樣式屬性。

// 獲取元素
var element = document.getElementById('myElement');

// 修改樣式屬性
element.style.color = 'red';
element.style.fontSize = '20px';

② 使用類名(透過新增/移除類名來改變樣式):

您可以透過新增或移除類名,間接改變元素的樣式。

// 獲取元素
var element = document.getElementById('myElement');

// 新增類名
element.classList.add('newStyle');

// 移除類名
element.classList.remove('oldStyle');

③ 使用CSS類庫(例如jQuery):

如果您使用jQuery等類庫,可以更方便地操作元素的樣式。

// 使用jQuery來改變樣式
$('#myElement').css('color', 'blue');

④ 動態計算樣式(計算樣式值並應用):

您可以透過計算樣式值來動態改變元素的樣式。

// 獲取元素
var element = document.getElementById('myElement');

// 計算樣式值
var newWidth = 100; // 例如,計算得到的新寬度

// 應用新樣式
element.style.width = newWidth + 'px';

這些方法可以幫助您在JavaScript中操作DOM元素的樣式,實現動態樣式變化和互動效果。根據您的需求和專案的複雜度,選擇最適合的方法來操作元素的樣式。

(7)事件

在JavaScript中,DOM(文件物件模型)提供了許多不同型別的事件,可以用於與使用者互動、操作文件內容和響應瀏覽器狀態的變化。

事件就是到達某個實現設定的條件,自動觸發的動作。

以下是一些常見的DOM事件型別及其詳細介紹:

① 滑鼠事件

  1. click:當使用者單擊元素時觸發。
  2. mouseover:當滑鼠移動到元素上方時觸發。
  3. mouseout:當滑鼠移出元素時觸發。
  4. mousedown:當滑鼠按下時觸發。
  5. mouseup:當滑鼠釋放時觸發。
  6. mousemove:當滑鼠在元素上移動時觸發。

② 鍵盤事件

  1. keydown:當使用者按下鍵盤上的任意鍵時觸發。
  2. keyup:當使用者釋放鍵盤上的鍵時觸發。
  3. keypress:當使用者按下鍵盤上的字元鍵時觸發。

③ 表單事件

  1. submit:當表單提交時觸發。
  2. change:當表單元素的值發生改變時觸發。
  3. input:當輸入框的值發生改變時觸發。
  4. focus:當元素獲得焦點時觸發。
  5. blur:當元素失去焦點時觸發。

④ 文件載入事件

  1. DOMContentLoaded:當初始 HTML 文件被完全載入和解析完成時觸發,不包括樣式表、圖片和子框架的載入。
  2. load:當整個頁面(包括樣式表、圖片等)被完全載入時觸發。

⑤ 定時器事件

  • setTimeout:在指定的延遲時間後觸發事件。
  • setInterval:每隔一定時間觸發事件。

⑥ 自定義事件:

  • 開發者可以根據需要建立自定義事件,並使用dispatchEvent來觸發事件。

⑦ 其他常見事件

  1. resize:當視窗或框架被調整大小時觸發。
  2. scroll:當元素的捲軸被滾動時觸發。
  3. error:當文件或元素髮生錯誤時觸發。

⑧示例程式碼

var button = document.getElementById("myButton");

button.addEventListener("click", function(event) {
  alert("按鈕被點選了!");
});
  • 以上示例程式碼中,當id為"myButton"的按鈕被點選時,會觸發點選事件,並彈出一個提示框。

這些是常見的DOM事件型別,您可以透過新增事件處理程式來捕獲這些事件,並對其做出相應處理。在開發網頁應用程式時,瞭解和使用這些事件將有助於實現更好的使用者互動和體驗。

(8)如何新增事件處理程式

您可以透過以下幾種方式向元素新增事件處理程式:

  1. HTML屬性:直接在HTML元素上使用事件屬性。例如:<button onclick="myFunction()">Click me</button>

  2. DOM屬性:透過JavaScript程式碼直接將事件處理程式新增到元素的事件屬性上。例如:

    var element = document.getElementById('myElement');
    element.onclick = function() {
        // 處理點選事件的程式碼
    };
    
  3. addEventListener方法:使用addEventListener方法向元素新增事件處理程式。這種方式可以新增多個事件處理程式。例如:

    element.addEventListener('click', function() {
        // 處理點選事件的程式碼
    });
    

補充:事件物件

當事件發生時,會建立一個事件物件,其中包含有關事件的資訊。您可以訪問事件物件的屬性和方法來獲取更多資訊,例如事件型別、目標元素等。

element.addEventListener('click', function(event) {
    console.log('事件型別:', event.type);
    console.log('目標元素:', event.target);
});

補充:阻止事件預設行為和事件傳播

在事件處理程式中,

  • 可以使用event.preventDefault()來阻止事件的預設行為,

  • 以及event.stopPropagation()來停止事件傳播。

element.addEventListener('click', function(event) {
    event.preventDefault(); // 阻止預設行為
    event.stopPropagation(); // 停止事件傳播
});

透過了解DOM事件以及如何新增事件處理程式,您可以更好地實現互動式的網頁應用程式,並對使用者的操作做出響應。

瞭解:事件監聽器

以下是一個簡單的 JavaScript DOM 事件處理的程式碼示例,演示瞭如何使用事件監聽器來響應使用者的點選事件:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>DOM 事件示例</title>
</head>
<body>
<button id="myButton">點選我</button>

<script>
// 獲取按鈕元素
const button = document.getElementById('myButton');

// 新增點選事件監聽器
button.addEventListener('click', function(event) {
    alert('按鈕被點選了!');
    console.log(event); // 列印事件物件到控制檯
});
</script>
</body>
</html>

在這個示例中,頁面上有一個按鈕元素,當使用者點選按鈕時,會觸發一個點選事件。透過使用addEventListener方法,我們為按鈕元素新增了一個點選事件監聽器。當按鈕被點選時,會彈出一個警告框顯示"按鈕被點選了!",同時在控制檯列印出事件物件event,以便開發者檢視事件的相關資訊。

您可以根據需要修改和擴充套件這個示例,以實現不同型別的互動和功能。透過使用事件處理程式,您可以在網頁中實現各種使用者互動,例如表單驗證、動態內容更新、動畫效果等。

思考題:

首先我們知道script標籤既可以放在head內,也可以放在body內,但是通常情況下都是放在body內的最底部,因為程式碼是從上往下載入的,需要先等待標籤結束再執行繫結事件的。

然後我如果非要放在head標籤內可以怎麼辦:

// 等待瀏覽器視窗載入完畢之後再執行程式碼
window.onload = function () {
	 // 第一種繫結事件的方式
    function func1(){
        alert(111)
    }
    // 第二種繫結事件的方式
    let btnEle = document.getElementById('d1');
    btnEle.onclick = function () {
        alert(222)
    }
}

四、BOM和DOM總結

DOM 是為了操作文件出現的 API,document 是其的一個物件;
BOM 是為了操作瀏覽器出現的 API,window 是其的一個物件。

BOM是瀏覽器物件模型,DOM是文件物件模型,前者是對瀏覽器本身進行操作,而後者是對瀏覽器(可看成容器)內的內容進行操作。

image

歸DOM管的:

  • E區(就是document了)由web開發人員嘔心瀝血寫出來的一個資料夾,裡面有index.html,CSS 和 JS 等等的,部署在伺服器上,我們可以透過瀏覽器的位址列輸入URL然後回車將這個document載入到本地,瀏覽,右鍵檢視原始碼等。

歸BOM管的:

  • A區(瀏覽器的標籤頁,位址列,搜尋欄,書籤欄,視窗放大還原關閉按鈕,選單欄等等)

  • B區(瀏覽器的右鍵選單)

  • C區(document載入時的狀態列,顯示http狀態碼等)

  • D區(捲軸scroll bar)

相關文章