日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 前端技术 > HTML >内容正文

HTML

提升对前端的认知,不得不了解Web API的DOM和BOM

發(fā)布時(shí)間:2023/12/4 HTML 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 提升对前端的认知,不得不了解Web API的DOM和BOM 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

了解Web API的DOM和BOM

  • 引言
  • 正文
  • 一、DOM操作
    • 1、DOM的本質(zhì)
    • 2、DOM節(jié)點(diǎn)操作
      • (1)property形式
      • (2)attribute形式
    • 3、DOM結(jié)構(gòu)操作
      • (1)新增/插入節(jié)點(diǎn)
      • (2)獲取子元素列表,獲取父元素
      • (3)刪除子元素
    • 4、DOM性能
    • (1)對DOM查詢做緩存
    • (2)將頻繁操作改為一次性操作
    • 5、回顧
  • 二、BOM操作
    • 1、navigator
    • 2、screen
    • 3、location
    • 4、history
  • 結(jié)束語

引言

在現(xiàn)代的開發(fā)中,vue和react都是很流行的開發(fā)框架,框架雖好用,但是框架的原理還是基于 DOM 操作去實(shí)現(xiàn)。如果一個(gè)前端工程師只會框架,不會 DOM ,那基本上是很容易被淘汰的。因?yàn)榭蚣艿拇婊顣r(shí)間我們誰也說不準(zhǔn),且技術(shù)更新迭代也特別快,說不定三五年就會被淘汰了都有可能。所以,扎實(shí)的學(xué)會 js 的基礎(chǔ)原理,不要被框架和一些外部事件所迷惑,對自己會有一個(gè)更好的競爭力提升。

本文將講解 JS 中 Web API 的 DOM 和 BOM 操作。

正文

一、DOM操作

DOM操作,即Document Object Model文檔對象模型。下面通過幾個(gè)知識點(diǎn)來分析DOM的本質(zhì)節(jié)點(diǎn)操作結(jié)構(gòu)操作以及 DOM 的性能。

1、DOM的本質(zhì)

DOM的本質(zhì)就是一棵 ,是樹結(jié)構(gòu)。

我們從早起xml說起,xml是一種可擴(kuò)展性的標(biāo)準(zhǔn)語言,早期基本是用xml來對DOM進(jìn)行編寫。具體形式如下:

<?xml version = "1.0" encoding = "UTF-8"?> <note><to>Tony</to><from>Abby</from><heading>London</heading><body>Have a nice day!</body><other><a></a><b></b></other> </note>

我們可以看到,一層一層的下來,層層遞進(jìn),很像一棵樹。


回到現(xiàn)在,我們基本上用的是 html 來進(jìn)行編寫。 html 也是一種特定的 xml ,只不過它是有自己的一套規(guī)范,比如說我們常見的 p 標(biāo)簽, span 標(biāo)簽, li 標(biāo)簽等等。引用百度來做一個(gè)解釋:

大家可以看到,上面一層一層遞進(jìn)的關(guān)系,把整個(gè) html 渲染出來形成我們看到的頁面,這一層層遞進(jìn)的關(guān)系,其實(shí)就是 DOM 樹,所以也可以說, DOM 是從 html 文件解析出來的一棵樹。

2、DOM節(jié)點(diǎn)操作

DOM節(jié)點(diǎn)主要有兩種操作,一種是property操作,另一種是attribute操作。下面讓我們來看看這兩種操作。

(1)property形式

html代碼:

<div id="div1" class="container"><p>文段 1</p><p>文段 2</p><p>文段 3</p> </div> <div id="div2"><img src="https://dss1.baidu.com/6ONXsjip0QIZ8tyhnq/it/u=2144980717,2336175712&fm=58" alt=""> </div>

JS代碼:

/*** property形式*/const pList = document.querySelectorAll('p');const p1 = pList[0];p1.style.width = '100px'; //修改樣式console.log(p1.style.width); //獲取樣式p1.className = 'red'; //修改class名稱console.log(p1.className); //獲取class名稱// 獲取nodeName和nodeTypeconsole.log(p1.nodeName); //打印節(jié)點(diǎn)名稱,pconsole.log(p1.nodeType); //打印節(jié)點(diǎn)類型,普通的DOM節(jié)點(diǎn)元素為1,文本類型是3

控制臺打印結(jié)果如下:

從上面的結(jié)果中可以看到,通過修改 DOM 的 JS 變量,從而操作 DOM ,最終得到我們想要的結(jié)果。

(2)attribute形式

html代碼:

<div id="div1" class="container"><p>文段 1</p><p>文段 2</p><p>文段 3</p> </div> <div id="div2"><img src="https://dss1.baidu.com/6ONXsjip0QIZ8tyhnq/it/u=2144980717,2336175712&fm=58" alt=""> </div>

JS代碼:

/*** attribute形式*/const pList = document.querySelectorAll('p');const p1 = pList[0];p1.setAttribute('data-name', 'immoc');console.log(p1.getAttribute('data-name'));p1.setAttribute('style', 'font-size:50px;');console.log(p1.getAttribute('style'));

控制臺打印結(jié)果如下:

從上面的結(jié)果中可以看到,通過修改 DOM 結(jié)構(gòu)的節(jié)點(diǎn)屬性,最終得到我們想要的結(jié)果。

綜上所述, porperty 和 attribute 這兩種操作類型,主要有以下區(qū)別:

  • property:修改對象屬性,不會體現(xiàn)到 html 結(jié)構(gòu)中;
  • attribute:修改 html 屬性,會改變 html 結(jié)構(gòu),即標(biāo)簽結(jié)構(gòu);
  • 兩者都有可能引起DOM重新渲染,但 attribute 引起 DOM 重新渲染的可能性更大,因?yàn)樗鼤膭?dòng) html 的結(jié)構(gòu)。所以在實(shí)際開發(fā)中,可以選擇的話盡量渲染 property 去操作 DOM 。

3、DOM結(jié)構(gòu)操作

通過上面的了解,我們都明白了DOM是一種樹結(jié)構(gòu)。那既然是樹結(jié)構(gòu),就應(yīng)該可以對節(jié)點(diǎn)進(jìn)行增刪改的操作。

因此,DOM結(jié)構(gòu)操作主要有以下三種類型:

  • 新增/插入節(jié)點(diǎn);
  • 獲取子元素列表,獲取父元素;
  • 刪除子元素。

接下來對這三種類型進(jìn)行講解。

(1)新增/插入節(jié)點(diǎn)

先附上html代碼。

<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title> </head> <body><div id="div1" class="container"><p id = "p1">文段 1</p><p>文段 2</p><p>文段 3</p></div><div id="div2"> <img src="https://dss1.baidu.com/6ONXsjip0QIZ8tyhnq/it/u=2144980717,2336175712&fm=58" alt=""></div><script src="./你的文件路徑.js"></script> </body> </html>

此時(shí)執(zhí)行狀態(tài)如下。

如果此時(shí)要給 div1 新增一個(gè)子節(jié)點(diǎn) p ,代碼如下。

// 新建節(jié)點(diǎn) const newP = document.createElement('p'); newP.innerHTML = 'this is newP'; // 插入節(jié)點(diǎn) div1.appendChild(newP);

此時(shí)瀏覽器執(zhí)行狀態(tài)如下。

大家可以看到, div1 成功新增了一個(gè)節(jié)點(diǎn),這就是關(guān)于新增節(jié)點(diǎn)操作的具體流程。

那如果在此基礎(chǔ)上,要移動(dòng)一個(gè)節(jié)點(diǎn)呢?具體操作如下。

// 移動(dòng)節(jié)點(diǎn) -> 把p1移動(dòng)到div2中來 const p1 = document.getElementById('p1'); div2.appendChild(p1);

此時(shí)瀏覽器執(zhí)行狀態(tài)如下。

(2)獲取子元素列表,獲取父元素

在上面的基礎(chǔ)上,我們來看看獲取父元素和子元素列表的流程。

// 獲取父元素 console.log(p1.parentNode);// 獲取子元素列表 const div1ChildNodes = div1.childNodes; console.log(div1ChildNodes); //此處獲取的包含p標(biāo)簽以及p標(biāo)簽下面的文本,因此需要一層過濾 const div1ChildNodesP = Array.prototype.slice.call(div1.childNodes).filter(child => {if(child.nodeType === 1){return true;}else{return false;} }); console.log('div1ChildNodesP', div1ChildNodesP);

此時(shí)瀏覽器執(zhí)行狀態(tài)如下。

(3)刪除子元素

在上面操作的基礎(chǔ)上,我們現(xiàn)在對 div1 中的第一個(gè) p 節(jié)點(diǎn)進(jìn)行移除。

// 移除元素 div1.removeChild(div1ChildNodesP[0]);

此時(shí)瀏覽器執(zhí)行狀態(tài)如下。

以上就是對DOM結(jié)構(gòu)的新增、移動(dòng)、獲取子父元素以及刪除子元素的一個(gè)操作,相信大家對DOM結(jié)構(gòu)的增刪改有了一個(gè)新的了解。接下來我們講解DOM性能。

4、DOM性能

為什么要對DOM做性能優(yōu)化呢,原因在于 DOM 操作是非?!鞍嘿F”的,每一次操作都很有可能引發(fā)瀏覽器的重排和重繪,因此要避免頻繁的 DOM 操作。那如何做到避免頻繁的 DOM 操作,給 DOM 進(jìn)行性能優(yōu)化呢?主要有以下兩個(gè)方面給 DOM 操作進(jìn)行性能優(yōu)化:

  • 對 DOM 查詢做緩存
  • 將頻繁操作改為一次性操作

接下來將對這兩種方法進(jìn)行講解。

(1)對DOM查詢做緩存

// 不緩存 DOM 查詢結(jié)果 for(let i = 0; i < document.getElementsByTagName('p').length; i++){// 每次循環(huán),都會計(jì)算length,頻繁進(jìn)行 DOM 查詢 } // 緩存 DOM 查詢結(jié)果 const pList = document.getElementsByTagName('p'); const length = pList.length; for(let i = 0; i < length; i++){// 緩存length,只進(jìn)行一次 DOM 查詢 }

分析以上兩段代碼,在第一段當(dāng)中,每次循環(huán)的時(shí)候,都會計(jì)算 length ,頻繁的對 DOM 進(jìn)行查詢,如此頻繁的操作,可想對程序都不是不太好的。

因此,通過優(yōu)化,我們寫出第二段代碼。在第二段代碼中,把 length 放在外部進(jìn)行緩存,等到每次循環(huán)的時(shí)候,只需要進(jìn)行一次 DOM 查詢,而不用像第一段一樣頻繁操作,極大提高了性能。

(2)將頻繁操作改為一次性操作

我們來看一個(gè)例子。比如說,我們先在要通過操作 DOM 來一次性插入10個(gè)列表。

在正常情況下我們想象的操作如下:

html代碼

<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title> </head> <body><div id="div1" class="container"><p id = "p1">文段 1</p><p>文段 2</p><p>文段 3</p></div><div id="div2"> <img src="https://dss1.baidu.com/6ONXsjip0QIZ8tyhnq/it/u=2144980717,2336175712&fm=58" alt=""></div><ul id="list"></ul><script src="./你的路徑.js"></script> </body> </html>

js代碼

const list = document.getElementById('list');for(let i = 0; i < 10; i++){const li = document.createElement('li');li.innerHTML = `List item ${i}`;list.appendChild(li); }

此時(shí)瀏覽器執(zhí)行狀態(tài)如下。

按照預(yù)想的,呈現(xiàn)出了我們想要的結(jié)果,且看著好像也沒什么問題。但是呢,這就違反了我們所說的一次性操作 DOM 的原則,因?yàn)樗陬l繁的操作 DOM ,一直在頻繁操作中修改。因此,我們可以通過以下方法來對性能做一個(gè)優(yōu)化:

/*** 頻繁操作改為一次性操作*/ const list = document.getElementById('list');// 創(chuàng)建一個(gè)文檔片段,此時(shí)還沒有插入到 DOM 結(jié)構(gòu)中 const frag = document.createDocumentFragment();for(let i = 0; i < 15; i++){const li = document.createElement('li');li.innerHTML = `List item ${i}`;//先插入文檔片段frag.appendChild(li); }// 都完成之后,再統(tǒng)一插入到 DOM 結(jié)構(gòu)中 list.appendChild(frag);

執(zhí)行后,瀏覽器也同樣效果呈現(xiàn)出來了。

通過代碼我們可以發(fā)現(xiàn),通過創(chuàng)建一個(gè)文檔片段,來對節(jié)點(diǎn)進(jìn)行一個(gè)緩存,等到全部節(jié)點(diǎn)操作都完成以后,再統(tǒng)一插入到 DOM 結(jié)構(gòu)中。這種方法,也極大提高了程序中的性能。

5、回顧

最后,我們用幾個(gè)題目來回顧DOM的知識點(diǎn)。

(1)DOM是哪一種數(shù)據(jù)結(jié)構(gòu)?

DOM是一種的數(shù)據(jù)結(jié)構(gòu),DOM也常被稱為DOM樹。

(2)DOM操作的常用API

(3)attribute和property的區(qū)別

兩者主要有以下區(qū)別:

  • property:修改對象屬性,不會體現(xiàn)到 html 結(jié)構(gòu)中;
  • attribute:修改 html 屬性,會改變 html 結(jié)構(gòu),即標(biāo)簽結(jié)構(gòu);
  • 兩者都有可能引起DOM重新渲染,但 attribute 引起 DOM 重新渲染的可能性更大,因?yàn)樗鼤膭?dòng) html 的結(jié)構(gòu)。所以在實(shí)際開發(fā)中,可以選擇的話盡量渲染 property 去操作 DOM 。

(4)一次性插入多個(gè)DOM節(jié)點(diǎn),需考慮性能,怎么操作?

可以通過創(chuàng)建一個(gè)Fragment的文檔片段,來對節(jié)點(diǎn)進(jìn)行一個(gè)緩存,等到 全部節(jié)點(diǎn)操作 都完成以后,再統(tǒng)一插入到 DOM 結(jié)構(gòu)中,從頻繁執(zhí)行改為一次執(zhí)行。

二、BOM操作

BOM,即Brouse Object Model瀏覽器對象模型。下面通過幾個(gè)知識點(diǎn)來了解瀏覽器的BOM操作。

1、navigator

navigator 主要用到 userAgent 屬性, navigator.userAgent 表示獲取瀏覽器的用戶代理字符串如以下代碼操作:

//navigator const ua = navigator.userAgent; console.log(ua); const isChrome = ua.indexOf('Chrome'); console.log(isChrome);

此時(shí)瀏覽器打印如下。

從上圖中可以看到,通過 userAgent 可以獲取到當(dāng)前所使用瀏覽器的內(nèi)核信息

2、screen

screen 主要用到width和height屬性,screen.width表示獲取當(dāng)前屏幕的寬度,sceen.height表示獲取當(dāng)前屏幕的高度。如以下代碼操作:

// screen console.log(screen.width); //獲取屏幕寬度 console.log(screen.height); //獲取屏幕高度

此時(shí)瀏覽器打印如下。

從上圖中可以看到,通過 screen.width 和 screen.height 可以獲取到當(dāng)前屏幕的寬度和高度。

3、location

location 主要用到 href/protocol/pathname/search/hash 屬性,具體含義如下代碼所示。

// location console.log(location.href); //獲取整個(gè)網(wǎng)址 console.log(location.protocol); //獲取網(wǎng)址協(xié)議 console.log(location.pathname); //獲取網(wǎng)址域名 console.log(location.search); //獲取網(wǎng)址中的一些參數(shù) console.log(location.hash); //獲取哈希值,即#號后面的值

此時(shí)瀏覽器打印如下。

相信從上圖的演示之后,大家對 location 屬性的應(yīng)用有了有一定的了解。

4、history

history 主要用到 back 和 forward 屬性,當(dāng)網(wǎng)頁執(zhí)行history.back()代碼時(shí),會將當(dāng)前網(wǎng)頁向后退一頁;當(dāng)網(wǎng)頁執(zhí)行history.forward()代碼時(shí),會將當(dāng)前網(wǎng)頁向前進(jìn)一頁。如以下代碼操作:

// history history.back(); //對網(wǎng)頁進(jìn)行后退 history.forward(); //對網(wǎng)頁進(jìn)行前進(jìn)

此時(shí)瀏覽器打印如下。

從上圖中可以看到,通過 history.back() 和 history.forward() 可以讓當(dāng)前瀏覽頁面進(jìn)行前進(jìn)或者后退操作。

結(jié)束語

JS 的基礎(chǔ)知識規(guī)定了 ECMA 的語法標(biāo)準(zhǔn),而 Web API 則是網(wǎng)頁操作的 API ,是 W3C 的標(biāo)準(zhǔn)。如果要說兩者的關(guān)系,那自然是 ES 標(biāo)準(zhǔn)是 Web API 的基礎(chǔ)。在實(shí)際應(yīng)用開發(fā)中,只有兩者結(jié)合才能真正做到實(shí)際應(yīng)用。所以,不管是 ES 標(biāo)準(zhǔn)還是 Web API 中的 DOM 和 BOM 操作,在實(shí)際開發(fā)中都是至關(guān)重要的內(nèi)容。

關(guān)于 DOM 和 BOM 的操作就講到這里啦!如有疑問歡迎評論區(qū)評論或私信我交流~

  • 關(guān)注公眾號 星期一研究室 ,不定期分享學(xué)習(xí)干貨

  • 如果這篇文章對你有用,記得點(diǎn)個(gè)贊加個(gè)關(guān)注哦~

總結(jié)

以上是生活随笔為你收集整理的提升对前端的认知,不得不了解Web API的DOM和BOM的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。