API(Application Programming Interface,應(yīng)用程序編程接口)是一些預(yù)先定義的函數(shù),API 是由語言本身或者運(yùn)行平臺提供的一系列特性和規(guī)則,通常是開發(fā)人員可以使用的一系列代碼特性,通常以對象的形式提供給開發(fā)人員,比如:數(shù)組對象,數(shù)組對象提供 length 屬性,以及 push/pop 等一些列的方法,這就是我們常用的 API,是由語言本身提供的 API。
API 目的是提供應(yīng)用程序與開發(fā)人員基于某軟件或硬件得以訪問一組例程的能力,而又無需訪問源碼,或理解內(nèi)部工作機(jī)制的細(xì)節(jié)。
Web API 是瀏覽器提供給我們操作瀏覽器和網(wǎng)頁文檔的一套編程接口。這是由 JavaScript 的運(yùn)行環(huán)境(此處是瀏覽器)提供的 API。通過瀏覽器提供的 API,我們可以實現(xiàn)彈窗效果(alert、prompt)、以及操作網(wǎng)頁文檔的能力,當(dāng)然還有很多涉及和硬件交互的 API,比如操作攝像頭、獲取地理位置等。
下面在學(xué)習(xí) BOM 和 DOM 之前,我們先來回顧下 JavaScript 組成:
BOM(Browser Object Model) 是指瀏覽器對象模型,瀏覽器對象模型提供了獨立于內(nèi)容的、可以與瀏覽器窗口進(jìn)行互動的對象結(jié)構(gòu)。BOM 由多個對象組成,其中代表瀏覽器窗口的 window 對象是 BOM 的頂層對象,其他對象都是該對象的子對象。
我們在瀏覽器中的一些操作都可以使用BOM的方式進(jìn)行編程處理
比如:刷新瀏覽器、后退、前進(jìn)、在瀏覽器中輸入URL等。
文檔對象模型(Document Object Model,簡稱DOM),是W3C組織推薦的處理可擴(kuò)展標(biāo)志語言的標(biāo)準(zhǔn)編程接口。在網(wǎng)頁上,組織頁面(或文檔)的對象被組織在一個樹形結(jié)構(gòu)中,用來表示文檔中對象的標(biāo)準(zhǔn)模型就稱為DOM。Document Object Model的歷史可以追溯至1990年代后期微軟與Netscape的“瀏覽器大戰(zhàn)”,雙方為了在JavaScript與JScript一決生死,于是大規(guī)模的賦予瀏覽器強(qiáng)大的功能。微軟在網(wǎng)頁技術(shù)上加入了不少專屬事物,既有VBScript、ActiveX、以及微軟自家的DHTML格式等,使不少網(wǎng)頁使用非微軟平臺及瀏覽器無法正常顯示。DOM即是當(dāng)時蘊(yùn)釀出來的杰作。
DOM 又稱為文檔樹模型,因為 HTML 文檔本身就是一個樹形結(jié)構(gòu),而 DOM 是使用面向?qū)ο蟮乃季S方式把 HTML 文檔以及 HTML 中的標(biāo)簽全部抽象成對象,瀏覽器在執(zhí)行的之后就會把網(wǎng)頁在內(nèi)存中構(gòu)建成 DOM 對象
如果 HTML 中的每一個標(biāo)簽/節(jié)點都是一個對象,我們就可以通過這個對象來操作 DOM 上的元素,比如:使用 JS 獲取頁面上的 div 對象,然后通過 div 對象的屬性或者方法控制 div 顯示或者隱藏。
DOM 是 JavaScript 操作網(wǎng)頁的接口,全稱為“文檔對象模型”(Document Object Model)。它的作用是將網(wǎng)頁轉(zhuǎn)為 JavaScript 對象,從而可以用腳本進(jìn)行各種操作(比如增刪內(nèi)容)。
瀏覽器會根據(jù) DOM 模型,將結(jié)構(gòu)化文檔(比如 HTML 和 XML)解析成一系列的節(jié)點,再由這些節(jié)點組成一個樹狀結(jié)構(gòu)(DOM Tree)。所有的節(jié)點和最終的樹狀結(jié)構(gòu),都有規(guī)范的對外接口。
DOM 只是一個接口規(guī)范,可以用各種語言實現(xiàn)。所以嚴(yán)格地說,DOM 不是 JavaScript 語法的一部分,但是 DOM 操作是 JavaScript 最常見的任務(wù),離開了 DOM,JavaScript 就無法控制網(wǎng)頁。另一方面,JavaScript 也是最常用于 DOM 操作的語言。后面介紹的就是 JavaScript 對 DOM 標(biāo)準(zhǔn)的實現(xiàn)和用法。
DOM 定義了訪問 HTML 和 XML 文檔的標(biāo)準(zhǔn):
“W3C 文檔對象模型 (DOM) 是中立于平臺和語言的接口,它允許程序和腳本動態(tài)地訪問和更新文檔的內(nèi)容、結(jié)構(gòu)和樣式?!?/p>
W3C DOM 標(biāo)準(zhǔn)被分為 3 個不同的部分:
XML DOM 定義了所有 XML 元素的對象和屬性,以及訪問它們的方法。
HTML DOM 定義了所有 HTML 元素的對象和屬性,以及訪問它們的方法。HTML DOM 是關(guān)于如何獲取、修改、添加或刪除 HTML 元素的標(biāo)準(zhǔn)。
DOM 的最小組成單位叫做節(jié)點(node)。文檔的樹形結(jié)構(gòu)(DOM 樹),就是由各種不同類型的節(jié)點組成。每個節(jié)點可以看作是文檔樹的一片葉子。節(jié)點也是對象。
節(jié)點的類型:
因為 DOM 文檔樹是一個樹形結(jié)構(gòu),樹形結(jié)構(gòu)中的節(jié)點包含兄弟、父子的關(guān)系,比如下圖中,body 是 h1、p、和 table 的父節(jié)點,同時 h1、p、table 是 body 的子節(jié)點。h1 p table 是兄弟節(jié)點。這點很重要后面節(jié)點操作中會通過這種方式獲取頁面上的元素。
例如我們要實現(xiàn)下圖中的美女畫廊,點擊第一排的小圖切換大圖和最底下圖片的描述,這個時候我們需要先獲取到小圖,并且讓小圖能夠點擊,最后修改顯示的大圖以及顯示的內(nèi)容。
根據(jù)上例總結(jié)未來我們常用的 DOM 操作是:獲取元素、注冊事件、操作元素。
首先我們來看為什么要獲取頁面元素,我們這里有一個需求:把 body 背景色變成黑色(模擬網(wǎng)頁中看視頻的關(guān)燈效果)。
思路:首先找到 body 元素,然后改變 body 的背景顏色
let body=document.body;
console.log(body);
body 是頁面內(nèi)主體標(biāo)簽,有特殊性,可快速獲取,但是 div 這類標(biāo)簽就不行。
下面我們來學(xué)習(xí)如何獲取頁面上的元素,這里我們先來介紹兩個獲取頁面元素的方法:
let div=document.getElementById(id)
console.log(div)
注意:由于id名具有唯一性,部分瀏覽器支持直接使用id名訪問元素,但不是標(biāo)準(zhǔn)方式,不推薦使用。
let divs=document.getElementsByTagName(tagName)
console.log(divs)
let divs=document.getElementsByTagName('div');
for (let i=0; i < divs.length; i++) {
let div=divs[i];
console.log(div);
}
注意:通過標(biāo)簽名獲取到的數(shù)據(jù)是偽數(shù)組,不管標(biāo)簽是一個還是多個,返回的都是偽數(shù)組。
返回的數(shù)據(jù)類型是 HTMLCollection 集合,HTMLCollection 是內(nèi)置類型,我們無法直接使用
點擊按鈕讓 div 的背景顏色改變?yōu)楹谏?/p>
let btn=document.getElementById('btn');
btn.onclick=function () {};
let div=document.getElementById('div');
div.style.background='black';
不同的 DOM 節(jié)點可能有不同的屬性。例如,標(biāo)簽 <a> 相對應(yīng)的元素節(jié)點具有鏈接相關(guān)的(link-related)屬性,標(biāo)簽 <input> 相對應(yīng)的元素節(jié)點具有與輸入相關(guān)的屬性等。文本節(jié)點與元素節(jié)點不同。但是所有這些標(biāo)簽對應(yīng)的 DOM 節(jié)點之間也存在共有的屬性和方法,因為所有類型的 DOM 節(jié)點都形成了一個單一層次的結(jié)構(gòu)。
每個 DOM 節(jié)點都屬于相應(yīng)的內(nèi)建類。
層次結(jié)構(gòu)的根節(jié)點是 EventTarget,Node 繼承自它,其他 DOM 節(jié)點繼承自 Node。
下圖做了進(jìn)一步說明:
因此,給定節(jié)點的全部屬性和方法都是繼承的結(jié)果。
通過 console.dir(div) 可以打印 div 元素的所有成員,在屬性的最下面可以看到當(dāng)前打印的 div 對象的類型是 HTMLDivElement,如下圖:
通過查詢 MDN 學(xué)習(xí)下面兩個獲取元素方法的使用方式:
注意:這兩個方法是 HTML5 以后新增,也是現(xiàn)在獲取元素最常用的方法
完成以下兩個功能:
Meta 對象
Meta 對象代表 HTML 的 一個 <meta> 元素。
<meta> 元素可提供有關(guān)某個 HTML 元素的元信息 (meta-information),比如描述、針對搜索引擎的關(guān)鍵詞以及刷新頻率。
Meta 對象屬性
W3C: W3C 標(biāo)準(zhǔn)。
屬性 | 描述 | W3C |
---|---|---|
content | 設(shè)置或返回 <meta> 元素的 content 屬性的值。 | Yes |
httpEquiv | 把 content 屬性連接到一個 HTTP 頭部。 | Yes |
name | 把 content 屬性連接到某個名稱。 | Yes |
scheme | 設(shè)置或返回用于解釋 content 屬性的值的格式。 | Yes |
標(biāo)準(zhǔn)屬性和事件
Meta 對象同樣支持標(biāo)準(zhǔn)的 屬性 和 事件。
如您還有不明白的可以在下面與我留言或是與我探討QQ群{{308855039},我們一起飛!
在Web開發(fā)中,尤其是在響應(yīng)式布局設(shè)計時,我們常常需要根據(jù)HTML元素的尺寸變化來調(diào)整頁面布局或內(nèi)容展示。Vue3 提供了強(qiáng)大的響應(yīng)式機(jī)制和Composition API,使得我們可以更靈活地監(jiān)聽并處理DOM元素尺寸的變化。本文將詳細(xì)介紹如何在Vue3項目中實現(xiàn)這一功能。
ResizeObserver 是瀏覽器提供的一個API,用于觀察目標(biāo)元素尺寸變化事件,并在其尺寸發(fā)生變化時觸發(fā)回調(diào)函數(shù)。首先引入 ResizeObserver 并創(chuàng)建一個觀察者實例:
import { onMounted, onUnmounted } from 'vue';
export default {
setup() {
const targetElement=ref(null); // 存儲需要監(jiān)聽的DOM元素引用
let resizeObserver;
// 當(dāng)組件掛載時創(chuàng)建ResizeObserver實例并開始監(jiān)聽
onMounted(()=> {
resizeObserver=new ResizeObserver((entries)=> {
entries.forEach((entry)=> {
console.log('Element size changed:', entry.contentRect.width, entry.contentRect.height);
// 在這里執(zhí)行相應(yīng)的邏輯處理
});
});
if (targetElement.value) {
resizeObserver.observe(targetElement.value);
}
});
// 組件卸載時停止監(jiān)聽
onUnmounted(()=> {
if (resizeObserver && targetElement.value) {
resizeObserver.unobserve(targetElement.value);
}
});
return {
targetElement,
};
},
};
在模板中,綁定目標(biāo)元素到 targetElement ref:
<div ref="targetElement">需要監(jiān)聽大小變化的元素</div>
為了更好地與Vue3的數(shù)據(jù)響應(yīng)性相結(jié)合,我們可以利用Ref或者Computed屬性來存儲和更新元素尺寸信息:
import { ref, computed, onMounted, onUnmounted } from 'vue';
export default {
setup() {
const targetElement=ref(null);
const elementSize=ref({ width: 0, height: 0 });
let resizeObserver;
onMounted(()=> {
resizeObserver=new ResizeObserver((entries)=> {
const entry=entries[0];
elementSize.value={
width: entry.contentRect.width,
height: entry.contentRect.height,
};
});
if (targetElement.value) {
resizeObserver.observe(targetElement.value);
}
});
onUnmounted(()=> {
if (resizeObserver && targetElement.value) {
resizeObserver.unobserve(targetElement.value);
}
});
// 創(chuàng)建一個計算屬性以返回最新尺寸信息
const reactiveElementSize=computed(()=> elementSize.value);
return {
targetElement,
reactiveElementSize,
};
},
};
現(xiàn)在你可以在其他組件內(nèi)部使用 reactiveElementSize 計算屬性來獲取實時的元素尺寸數(shù)據(jù),并據(jù)此做出相應(yīng)布局調(diào)整。
在上述代碼示例中,elementSize 用于存儲元素的尺寸信息(寬度和高度),我們使用了 ref 來定義它。然而,如果你希望 elementSize 對象本身具有響應(yīng)性,即當(dāng)對象內(nèi)部的屬性發(fā)生變化時也能觸發(fā)視圖更新,那么使用 reactive 可能會更合適。
import { ref, reactive, onMounted, onUnmounted } from 'vue';
export default {
setup() {
const targetElement=ref(null);
// 使用reactive創(chuàng)建響應(yīng)式對象
const elementSize=reactive({ width: 0, height: 0 });
let resizeObserver;
onMounted(()=> {
resizeObserver=new ResizeObserver((entries)=> {
const entry=entries[0];
// 直接修改響應(yīng)式對象內(nèi)部屬性
elementSize.width=entry.contentRect.width;
elementSize.height=entry.contentRect.height;
});
if (targetElement.value) {
resizeObserver.observe(targetElement.value);
}
});
onUnmounted(()=> {
if (resizeObserver && targetElement.value) {
resizeObserver.unobserve(targetElement.value);
}
});
return {
targetElement,
elementSize,
};
},
};
在這種情況下,因為 elementSize 是一個由 reactive 創(chuàng)建的響應(yīng)式對象,所以在其內(nèi)部屬性 width 和 height 發(fā)生變化時,依賴這些值的組件也會自動重新渲染,無需額外的操作。
需要注意的是,在實際應(yīng)用中,如果只是簡單的尺寸數(shù)值,使用 ref 足以滿足需求,因為 ref 的 .value 屬性本身就是響應(yīng)式的。而 reactive 更適用于需要整個對象結(jié)構(gòu)都具有響應(yīng)性的場景。
Vue3 的 Composition API 結(jié)合瀏覽器原生的 ResizeObserver 可以為我們在監(jiān)聽HTML元素尺寸變化上提供強(qiáng)大而靈活的支持。通過這樣的方式,開發(fā)者可以輕松應(yīng)對各種復(fù)雜的響應(yīng)式布局需求,為用戶帶來更好的交互體驗。同時,借助Vue3的數(shù)據(jù)響應(yīng)性和自動更新機(jī)制,能夠在元素尺寸變化時及時刷新視圖,保持UI狀態(tài)與實際DOM的一致性。
*請認(rèn)真填寫需求信息,我們會在24小時內(nèi)與您取得聯(lián)系。