第五節(jié) DOM節(jié)點樹和時間定時器


DOM: Document Object Model(文檔對象模型)

DOM樹:


回流和重繪

重繪(repaint):

當(dāng)元素樣式的改變不影響布局時,瀏覽器將使用重繪對元素進(jìn)行更新,此時由于只需要 UI 層面的重新像素繪制,因此損耗較少。

常見的重繪操作有:

改變元素顏色

改變元素背景色

more ……

回流(reflow):

又叫重排(layout)。當(dāng)元素的尺寸、結(jié)構(gòu)或者觸發(fā)某些屬性時,瀏覽器會重新渲染頁面,稱為回流。此時,瀏覽器需要重新經(jīng)過計算,計算后還需要重新頁面布局,因此是較重的操作。

常見的回流操作有

頁面初次渲染

瀏覽器窗口大小改變

元素尺寸/位置/內(nèi)容發(fā)生改變

元素字體大小變化

添加或者刪除可見的 DOM 元素

……

重點:回流必定會觸發(fā)重繪,重繪不一定會觸發(fā)回流。重繪的開銷較小,回流的代價較高。

DOM 操作


1、獲取元素

1.1 根據(jù)id名獲取

document.getElementById(idName)

1.2 根據(jù)標(biāo)簽名獲取

document.getElementsByTagName(tagName)? // 返回一個集合 (類數(shù)組對象)? 從整個文檔獲取

element.getElementsByTagName(tagName)? ? // 從element的后代元素中獲取

1.3 根據(jù)類名獲?。ú患嫒輎e6~8)

document.getElementsByClassName(className)? // 返回一個集合(類數(shù)組對象)? 從整個文檔獲取

element.getElementsByClassName(className)? // 從element的后代中獲取

1.4 根據(jù) name 屬性值獲取

正常的規(guī)范中,咱們只會給表單元素起name值,如果給其它元素設(shè)置name,在ie9以下版本瀏覽器不兼容,是獲取不到的,

所以為了這種情況,咱們以后養(yǎng)成習(xí)慣,只給表單元素用name,非表單元素不用name

document.getElementsByName()? //返回集合? 只有document才有該方法

1.5 根據(jù)選擇器獲取

注意:querySelector 和querySelectorAll 在ie6-ie8 下不兼容

document.querySelector(選擇器)? //選擇器第一個滿足選擇器條件的

document.querySelectorAll(選擇器) //選擇所有滿足選擇器條件的,返回nodeList(類數(shù)組對象)

element.querySelector(選擇器)

element.querySelectorAll(選擇器)

1.6 document.head?

? ? ? 獲取Head元素對象

1.7? document.body

? ? 獲取body元素對象

1.8 document.documentElement

? ?獲取html元素對象

2、獲取一屏幕的寬度或者高度,兼容所有的瀏覽器

// 獲取一屏幕的高度

varvH=document.documentElement.clientHeight||document.body.clientHeight;

// 偶去一屏幕的寬度

varvW=document.documentElement.clientWidth||document.body.clientWidth;

3、id小妙招?直接把id當(dāng)成變量去用的時候,可以獲取相應(yīng)的id元素。(瀏覽器的機(jī)制)

<script>

console.log(box1)

</script>

2、節(jié)點

●文檔節(jié)點●屬性節(jié)點●元素節(jié)點●文本節(jié)點●注釋節(jié)點

2.1 文檔節(jié)點

●nodeType(節(jié)點類型):9●nodeName(節(jié)點名稱):"#document"●nodeValue(節(jié)點值):null

document.nodeType;

document.nodeName

document.nodeValue;

2.2 屬性節(jié)點

●nodeType:2●nodeName:屬性名●nodeValue:屬性值getAttributeNode() 方法從當(dāng)前元素中通過名稱獲取屬性節(jié)點。

vara1=a1.getAttributeNode("href");// 獲取屬性節(jié)點

console.log(a1.nodeType);//2

console.log(a1.nodeName);//"href"; 屬性名

console.log(a1.nodeValue);//"http://www.baidu.com"; 屬性值

2.3 元素節(jié)點

●nodeType:1●nodeName:大寫的標(biāo)簽名●nodeValue:null

<script>

console.log(box.nodeName)

</script>

2.4 文本節(jié)點

●nodeType:3●nodeName:"#text"●nodeValue:文本內(nèi)容●在標(biāo)準(zhǔn)瀏覽器中,換行和空格也屬于文本節(jié)點

varres=a1.childNodes[0];

console.log(res.nodeType);//3

console.log(res.nodeValue);//"百度";

console.log(res.nodeName);//"#text";

2.5 注釋節(jié)點

●nodeType:8●nodeName:"#comment"●nodeValue:注釋的內(nèi)容

<!--a標(biāo)簽-->

百度

</a>

a1.childNodes;//NodeList(3)?[text, comment, text]

a1.childNodes[1].nodeName;//"#comment"

a1.childNodes[1].nodeType;//8

a1.childNodes[1].nodeValue;//"a標(biāo)簽 "

3、節(jié)點之間關(guān)系的屬性

節(jié)點類:

parentNode? ? 父節(jié)點

childNodes? ? 所有子節(jié)點的集合

firstChild? ? 第一個子節(jié)點

lastChild? ? 最后一個子節(jié)點

previousSibling? 上一個兄弟節(jié)點

nextSibling? ? ? 下一個兄弟節(jié)點

元素類:

children? ? 所有子元素的集合

firstElementChild? 第一個子元素? IE9+

lastElementChild? ? 最后一個子元素 IE9+

previousElementSibling? 上一個兄弟元素 IE9+

nextElementSibling? ? 下一個兄弟元素? IE9+

3.1 parentNode獲取當(dāng)前節(jié)點唯一的父親節(jié)點

<div>

<!--111-->

<div id="box">111</div>

</div>

</div>

<script>

console.log(box.parentNode)

</script>

3.2 childNodes獲取當(dāng)前節(jié)點所有的子節(jié)點

<!--我是注釋-->

<li>選擇珠峰的,都是明智的!</li>

<li>選擇珠峰的,都是明智的!</li>

<li>選擇珠峰的,都是明智的!</li>

<li>選擇珠峰的,都是明智的!</li>

</ul>

<script>

console.log(main.childNodes);//NodeList(11)?[text, comment, text, li, text, li, text, li, text, li, text]

3.3 firstChild獲取被選節(jié)點的第一個子節(jié)點。

<!--我是注釋-->

<li>選擇珠峰的,都是明智的!</li>

<li>選擇珠峰的,都是明智的!</li>

<li>選擇珠峰的,都是明智的!</li>

<li>選擇珠峰的,都是明智的!</li>

</ul>

<script>

console.log(main.firstChild);//#text

3.4 lastChild獲取被選節(jié)點的最后一個子節(jié)點

<!--我是注釋-->

<li>選擇珠峰的,都是明智的!</li>

<li>選擇珠峰的,都是明智的!</li>

<li>選擇珠峰的,都是明智的!</li>

<li>選擇珠峰的,都是明智的!</li>

</ul>

<script>

console.log(main.lastChild);//#text

3.5 previousSibling獲取上一個哥哥節(jié)點

<!--我是注釋-->

<li>選擇珠峰的,都是明智的!</li>

<li>選擇珠峰的,都是明智的!</li>

<li>選擇珠峰的,都是明智的!</li>

<li>選擇珠峰的,都是明智的!</li>

</ul>

<script>

console.log(main.previousSibling);//#text

3.6 nextSibling獲取當(dāng)前節(jié)點的下一個兄弟節(jié)點

<!--我是注釋-->

<li>選擇珠峰的,都是明智的!</li>

<li>選擇珠峰的,都是明智的!</li>

<li>選擇珠峰的,都是明智的!</li>

<li>選擇珠峰的,都是明智的!</li>

</ul><!-- 1111 -->

<script>

console.log(main.nextSibling);//<!-- 1111 -->

3.7 children獲取當(dāng)前元素所有的元素子節(jié)點,但是在ie6--ie8下不兼容3.8 firstElementChild獲取當(dāng)前節(jié)點的第一個元素子節(jié)點 ie6-ie8 不兼容

<li>選擇珠峰的,都是明智的!</li>

<li>選擇珠峰的,都是明智的!</li>

<li>選擇珠峰的,都是明智的!</li>

<li>選擇珠峰的,都是明智的!</li>

</ul>

<script>

console.log(main.firstElementChild);

3.9 lastElementChild獲取當(dāng)前節(jié)點的最后一個元素子節(jié)點? ie6-ie8 不兼容

<li>選擇珠峰的,都是明智的!</li>

<li>選擇珠峰的,都是明智的!</li>

<li>選擇珠峰的,都是明智的!</li>

<li>選擇珠峰的,都是明智的!111</li>

</ul>

<script>

console.log(main.lastElementChild);

3.10 previousElementSibling獲取上一個哥哥元素節(jié)點? ie6-ie8 不兼容<ul id="main">

<li>選擇珠峰的,都是明智的!</li>

<li>選擇珠峰的,都是明智的!</li>

<li>選擇珠峰的,都是明智的!</li>

<li>選擇珠峰的,都是明智的!111</li>

</ul>

<script>

console.log(main.previousElementSibling);

3.11 nextElementSibling獲取當(dāng)前節(jié)點的下一個兄弟元素節(jié)點? ? ie6-ie8 不兼容

<ul id="main">

<li>選擇珠峰的,都是明智的!</li>

<li>選擇珠峰的,都是明智的!</li>

<li>選擇珠峰的,都是明智的!</li>

<li>選擇珠峰的,都是明智的!111</li>

</ul>

<script>

console.log(main.nextElementSibling);

練習(xí)題

自己手動封裝一個獲取節(jié)點下面的所有子元素,要求考慮兼容性。

<html lang="en">

<head>

<meta charset="UTF-8">

<meta name="viewport"content="width=device-width, initial-scale=1.0">

<meta http-equiv="X-UA-Compatible"content="ie=edge">

<title>Document</title>

<style>


</style>

</head>

<body>

<span id="span1">1</span>

<ul id="main">

<!--我是注釋-->

<li>選擇珠峰的,都是明智的!</li>

<li>選擇珠峰的,都是明智的!</li>

<li>選擇珠峰的,都是明智的!</li>

<li>選擇珠峰的,都是明智的!</li>

</ul>

<span>2</span>

</body>

</html>

<script>

functionchildren(element){

varnodeLists=element.childNodes;

varresult=[]

for(vari=0;i<nodeLists.length;i++){

nodeLists[i].nodeType===1?result.push(nodeLists[i]):null;

}

returnresult;

}

console.log(children(main));

自己手動封裝一個previousElementSibling,要兼容。

<html lang="en">

<head>

<meta charset="UTF-8">

<meta name="viewport"content="width=device-width, initial-scale=1.0">

<meta http-equiv="X-UA-Compatible"content="ie=edge">

<title>Document</title>

<style>


</style>

</head>

<body>

<span id="span1">1</span>

<ul id="main">

<!--我是注釋-->

<li>選擇珠峰的,都是明智的!</li>

<li>選擇珠峰的,都是明智的!</li>

<li>選擇珠峰的,都是明智的!</li>

<li>選擇珠峰的,都是明智的!</li>

</ul>

<span id="span2">2</span>

</body>

</html>

<script>

functionpreviousElmentSibling(ele){

varpre=ele.previousSibling;

while(pre&&pre.nodeType!==1){

pre=pre.previousSibling;

}

returnpre;

}

console.log(previousElmentSibling(span2))

</script>

DOM 的增刪改

1、createElement:創(chuàng)建一個元素

document.createElement("div");

2、createTextNode: 創(chuàng)建一個文本節(jié)點

var otext=document.createTextNode("哈哈!");

3、appendChild:把元素追加到一個容器的末尾

語法:[context].appendChild([元素]);

<div id="id1"></div>

? <script>

? ? var odiv = document.createElement("div");

? ? id1.appendChild(odiv);

? ? console.log(id1)

? </script>

4、insertBefore: 把一個元素插入到另一個元素的前面

首先要指定一個父節(jié)點

var? insertedNode = 父節(jié)點.insertBefore(要插入的節(jié)點, 插在這個節(jié)點之前)

var? insertedNode = parentNode.insertBefore(newNode, referenceNode)

newNode:將要插入的節(jié)點

referenceNode:被參照的節(jié)點(即要插在該節(jié)點之前)

insertedNode:插入后的節(jié)點

parentNode:父節(jié)點

<div id="id1">

? <p class="p1" id="p1">這是P1</p>

</div>

<script>

? var div = document.getElementById('id1');

? var p1 = document.getElementById('p1');

? var odiv = document.createElement("div");

? var returnDom = div.insertBefore(odiv, p1);

console.log(div)

</script>

5、cloneNode:把某一個節(jié)點進(jìn)行克隆

【ele】.cloneNode();淺克?。?只是克隆了一個節(jié)點,里面的內(nèi)容還有樣式都沒克隆

【ele】.cloneNode(true);深克隆:把節(jié)點包含的所有內(nèi)容進(jìn)行克隆

<div id="id1">

? ? <p class="p1" id="p1">這是P1</p>

? </div>

? <script>

? ? var res = id1.cloneNode();

? ? var res2 = id1.cloneNode(true)

? ? console.log(res)

? ? console.log(res2)

? </script>

6、removeChild:移除某個節(jié)點

【context】.removeChild(ele);

<div id="id1">

? ? 1111

? ? <p class="p1" id="p1">這是P1</p>

? </div>

? <script>

? ? id1.removeChild(p1);

? ? console.log(id1)

? </script>

7、set/get/removeAttribute

設(shè)置/獲取/刪除 當(dāng)前元素的某一個自定義屬性

setAttribute

getAttribute

removeAttribute

box.setAttribute("index", 1);

box.getAttribute("index");

box.removeAttribute("index");

console.log(box)

// 設(shè)置

// box["aa"] = 22;

// 獲取

// box["aa"]

//移除

// delete box["aa"];

基于鍵值對方式 增刪改:修改當(dāng)前對象的堆內(nèi)存空間完成的(在堆內(nèi)存空間可以看到)

基于Attribute dom方法增刪改,是修改html結(jié)構(gòu)來完成的(此種方法設(shè)置的在結(jié)構(gòu)上可以看到)

以上兩種方式不能混用

題目

利用a標(biāo)簽的href來重新獲取url參數(shù)

var str = "http://www.zhufengpeixun.cn?name=lili&age=18#123"

<!DOCTYPE html>

<html lang="en">

<head>

? <meta charset="UTF-8">

? <meta name="viewport" content="width=device-width, initial-scale=1.0">

? <title>Document</title>

</head>

<body>

? <script>

? ? var str = "http://www.zhufengpeixun.cn?name=lili&age=18#123"

? ? /*

? ? search: "?name=lili&age=18"

? ? hash: "#123"

? ? */

? ? function queryParams(str) {

? ? ? var a = document.createElement("a");

? ? ? a.href = str;

? ? ? var obj = {};

? ? ? console.log(a.search); //?name=lili&age=18

? ? ? console.log(a.hash); //#123

? ? ? //[name=lili,age=18]

? ? ? var search = a.search.substr(1);

? ? ? console.log(search);//name=lili&age=18

? ? ? obj.hash = a.hash ? a.hash : null;

? ? ? if (search) {

? ? ? ? var searchAry = search.split("&");

? ? ? ? console.log(searchAry)//?['name=lili', 'age=18']

? ? ? ? for (var i = 0; i < searchAry.length; i++) {

? ? ? ? ? var itemAry = searchAry[i];//name=lili? age=18

? ? ? ? ? var item = itemAry.split("=");

? ? ? ? ? console.log(item)//['name', 'lili']['age', '18']

? ? ? ? ? var key = item[0];

? ? ? ? ? var value = item[1];

? ? ? ? ? obj[key] = value;

? ? ? ? }

? ? ? }

? ? ? return obj;

? ? }

? ? var dd = queryParams(str);

? ? console.log(dd)

? </script>

</body>

</html>




1、時間對象

1.1【作用】:Date 對象用于處理日期和時間。

1.2【創(chuàng)建時間對象】: new Date()獲取系統(tǒng)當(dāng)前時間

var myDate=new Date(); //Tue Dec 24 2019 20:44:00 GMT+0800 (中國標(biāo)準(zhǔn)時間);

typeof myDate;====>"object"? // 獲取到是一個對象,并不是字符串

1.3 時間對象相關(guān)屬性和方法

●getFullYear();獲取年●getMonth();獲取月 0到11 代表1月到12月●getDate();獲取日期●getDay();星期幾 (0---6)代表周日到到周六●getHours();時●getMinutes();分●getSeconds();秒●getMilliseconds();毫秒●getTime();獲取當(dāng)前日期到1970年1月1號 00:00:00 之間的毫秒差●toLocaleString();// 獲取到的是年月日,時分秒"2019/12/25 上午10:15:50"●toLocaleDateString();//? 獲取到是字符串的年月日,例如:"2019/12/25"●toLocaleTimeString();/ 獲取到的是字符串的時分秒上午10:18:28

2、案例:鐘表

<html lang="en">

<head>

<meta charset="UTF-8">

<meta name="viewport"content="width=device-width, initial-scale=1.0">

<meta http-equiv="X-UA-Compatible"content="ie=edge">

<title>Document</title>

<style>

#clock{

height:50px;

line-height:50px;

text-align:center;

}

</head>

<body>

<div class="clock"id="clock">

</div>

<script>

functionclock(){

vartime=newDate;

varyear=time.getFullYear();

varmonth=time.getMonth()+1;//0-11 代表1月到12月

vardate=time.getDate();//日期

varday=time.getDay();//0-6代表周日到到六

varhours=time.getHours();

varminutes=time.getMinutes();

varseconds=time.getSeconds();

varweekStr=["日","一","二","三","四","五","六"];

varweek=weekStr[day];

varresult=year+"年"+month+"月"+date+"日"+"周"+week;

result+=hours+"時"+minutes+"分"+seconds+"秒";

returnresult;

}

vartime=clock();

document.getElementById("clock").innerHTML=time;

setInterval(function(){

vartime=clock();

document.getElementById("clock").innerHTML=time;

},1000)

</script>

</body>

</html>

補(bǔ)0操作:

<html lang="en">

<head>

<meta charset="UTF-8">

<meta name="viewport"content="width=device-width, initial-scale=1.0">

<meta http-equiv="X-UA-Compatible"content="ie=edge">

<title>Document</title>

<style>

#clock{

height:50px;

line-height:50px;

text-align:center;

}

</head>

<body>

<div class="clock"id="clock">

</div>

<script>

varclock=document.getElementById("clock");

functiongetTime(){

vartime=newDate();

varyear=time.getFullYear();

varmonth=time.getMonth()+1;

vardate=time.getDate();

varday=time.getDay();

varhour=time.getHours();

varminutes=time.getMinutes();

varseconds=time.getSeconds();

varweek=["周日","周一","周二","周三","周四","周五","周六"];

varres=year+"年"+addZero(month)+"月"+addZero(date)+"日"+week[day]+" "+addZero(hour)+":"+addZero(minutes)+":"+addZero(seconds);

returnres;

}

functionaddZero(num){

returnnum<10?"0"+num:num;

}

varres=getTime();

clock.innerText=res;

setInterval(function(){

varres=getTime();

clock.innerText=res;

},1000)

</script>

</body>

</html>

3、定時器:

3.1、setTimeOut? ?

??一定的時間后,去執(zhí)行某些事情,是單次調(diào)用

setTimeout(function(){

? ? alert("wasai!you are beautiful");

},1000)

3.2、setInterval

間隔多少時間后,去執(zhí)行某些事情,是多次調(diào)用

setInterval(function(){

console.log("我真美!")

},1000)

3.3、定時器的參數(shù)說明

// 定時器可以傳遞多個參數(shù):

// 1、執(zhí)行的函數(shù)

// 2、時間

// 3、后面的參數(shù)就是執(zhí)行函數(shù)在執(zhí)行的時候傳遞的實參

setTimeout(function(num,s,m){

console.log(num,s,m);

},1000,2,3,6);

3.4、定時器是有返回值的,返回值代表定時器處于當(dāng)前頁面中的第幾個

vartime1=setTimeout(function(){

console.log("wasai!you are beautiful");

},1000)

vartime2=setInterval(function(){

console.log("我真美!")

},1000)

vartime3=setTimeout(function(){

console.log("aa");

},1000)

console.log(time1)=====>1

console.log(time1)=====>2

console.log(time1)=====>3

3.5、定時器是異步任務(wù),只要當(dāng)咱們同步代碼執(zhí)行完畢之后,才能執(zhí)行。

setTimeout(function(){

console.log("定時器");

},1000)

console.log("haha")

4、清除定時器的方法

●clearTimeout●clearInterval

5、練習(xí)

做一個抽獎程序,頁面中有一個區(qū)域顯示中獎人員的編號,在JS中寫一段代碼,要求每隔1秒中隨機(jī)創(chuàng)建一個四位的數(shù)字(每一位數(shù)字的取值范圍0-9),當(dāng)10秒結(jié)束后,結(jié)束定時器,最后顯示的四位數(shù)字即是中獎的號碼

<!DOCTYPE html>

<html lang="en">

<head>

? ? <meta charset="UTF-8">

? ? <meta name="viewport" content="width=device-width, initial-scale=1.0">

? ? <meta http-equiv="X-UA-Compatible" content="ie=edge">

? ? <title>中獎</title>

? ? <style>

? ? #prize{

? ? ? ? width:200px;

? ? ? ? height:50px;

? ? ? ? border:1px solid green;

? ? }

? ? </style>

</head>

<body>

? ? <div class="prize" id="prize"></div>

</body>

</html>

<script>

? ? function getCode(){

? ? ? ? var str="0123456789";

? ? ? ? var result="";

? ? ? ? for(var i=0;i<4;i++){

? ? ? ? ? ? var index=Math.floor(Math.random()*9);

? ? ? ? ? ? result+=str[index];

? ? ? ? }

? ? ? prize.innerHTML=result;

? ? ? return result;

? ? }

? ? var time1=setInterval(function(){

? ? ? ? getCode();

? ? },1000);

? ? setTimeout(function(){

? ? ? ? clearInterval(time1);

? ? },10000)



</script>

倒計時案例:

<html lang="en">

<head>

<meta charset="UTF-8">

<meta name="viewport"content="width=device-width, initial-scale=1.0">

<meta http-equiv="X-UA-Compatible"content="ie=edge">

<title>Document</title>

<style>

*{

margin:0;

padding:0;

}

body {

background:darkslateblue;

}

#time{

height:100px;

line-height:100px;

border:1px dashed yellow;

text-align:center;

color:#fff;

font-size:26px;

}

</head>

<body>

<div id="time">

</div>

<script>

/*

? ? ? 倒計時:

? ? ? 目標(biāo)時間:2021年12月14號

? ? ? 目標(biāo)時間-現(xiàn)在的時候=還剩多少時間?

? ? ? 為了方便計算時間差,我們統(tǒng)一轉(zhuǎn)成到1970年...的時間戳

? ? */

functioncountDown(targetStr){

// 目標(biāo)時間

vartargetTime=newDate(targetStr);

// 現(xiàn)在的時間

varnowTime=newDate()

// 時間差,得出來的是毫秒

vardiffTime=targetTime-nowTime;

// 把時間差換算成時、分、秒

varhours=Math.floor(diffTime/(1000*60*60));

varminutes=Math.floor((diffTime-hours*1000*60*60)/(1000*60));

varseconds=Math.floor((diffTime-hours*1000*60*60-minutes*60*1000)/1000);

varresult=formatter(hours)+"時"+formatter(minutes)+"分"+formatter(seconds)+"秒";

returnresult;

}

functionformatter(val){

returnval=Number(val)<10?"0"+val:val;

}

varres=countDown("2021-12-24 00:00:00");

time.innerHTML=res;

console.log(res)

setInterval(()=>{

varres=countDown("2021-12-24 00:00:00");

time.innerHTML=res;

},1000);

</body>

</html>

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容