js學習筆記——(10)DOM基礎詳解

一、DOM簡介

1.什麼是DOM
文檔對象模型,是W3C組織推薦的處理可擴展標記語言(HTML和XMI)的標準編程接口。

W3C已經定義了一系列的DOM接口,通過這些DOM接口可以改變網頁的內容、結構和樣式。

2.DOM樹
文檔:一個頁面就是一個文檔,DOM中使用document表示。
元素:頁面中的所有標籤都是元素,DOM中使用element表示。
節點:頁面中的所有內容都是節點(標籤、屬性、文本、註釋等),DOM中使用node表示

DOM把以上內容都看作是對象

二、獲取元素

1.如何獲取頁面元素
獲取頁面中的元素可以使用以下幾種方式:

a.根據ID獲取
使用getElementById()方法可以獲取帶有ID的元素對象。

<body>
	<div id="timer">2019-9-9</div>
	<script>
		//1.文檔從上往下加載,js寫在下面
		//2.get獲得element元素by通過  駝峯命名法
		//3.參數  id 區分大小寫
		//4.返回的是一個元素對象
		var timer = document.getElementById("timer");
		console.log(timer);
		console.log(typeof timer);
		//5.console.dir 打印我們返回的元素對象  更好的查看裏面屬性和方法
		console.dir(timer);
	</script>
</body>

b.根據標籤名獲取
getElementsByTagName()方法可以返回帶有指定標籤名的對象的集合

<body>
	<ul>
		<li>知否知否,應是等你好久!1</li>
		<li>知否知否,應是等你好久!2</li>
		<li>知否知否,應是等你好久!3</li>
		<li>知否知否,應是等你好久!4</li>
		<li>知否知否,應是等你好久!5</li>
	</ul>
	<ul id = "nav">
		<li>生僻字</li>
		<li>生僻字</li>
		<li>生僻字</li>
		<li>生僻字</li>
		<li>生僻字</li>
	</ul>
	<script>
		//1.返回的是獲取過來元素對象的集合  以僞數組形式存儲
		var lis = document.getElementsByTagName("li");
		console.log(lis);
		console.log(lis[0]);
		//2.我們想要依次打印裏面的元素對象我們可以採取遍歷的方式
		for(var i = 0; i <lis.length; i++){
			console.log(lis[i]);
		}
		//3.element.getElementsByTagName() 可以得到這個元素裏面的某些
		var nav = document.getElementById('nav');
		var navLis = nav.getElementsByTagName('li');
		console.log(navLis);
	</script>
</body>

注意:
(1)因爲得到的是一個對象的集合,所以我們操作裏面元素就需要遍歷。
(2)得到元素對象是動態的

c.通過HTML5新增的方法獲取
1.getElementsByClassName(‘類名’);根據類名返回元素對象集合。
2.document.querySelector(‘選擇器’);根據指定選擇器返回第一個元素對象。
3.document.querySelectorAll(‘選擇器’);根據指定選擇器返回。

<body>
	<div class="box">盒子</div>
	<div class="box">盒子</div>
	<div id="nav">
		<ul>
			<li>首頁</li>
			<li>產品</li>
		</ul>
	</div>
	<script>
		//1.getElementsByClassName 根據類名獲得某些元素的1集合
		var boxs = document.getElementsByClassName('box');
		console.log(boxs);
		//2.querySelector  返回指定選擇器的第一個元素對象  切記裏面的選擇器要加符號 .box   #nav 
		var firstBox = document.querySelector('.box');
		console.log(firstBox);
		var nav = document.querySelector('#nav');
		console.log(nav);
		var li = document.querySelector('li');
		console.log(li);
		//3.querySelectorAll() 返回指定選擇器的所有元素對象集合
		var allBox = document.querySelectorAll('.box');
		console.log(allBox);
		var lis = document.querySelectorAll('li');
		console.log(lis);
	</script>
</body>

d.特殊元素獲取
獲取body元素
document.body;
獲取html元素
document.documentElement;

<body>
	<script>
		//1.獲取body元素
		var bodyEle = document.body;
		console.log(bodyEle);
		console.dir(bodyEle);
		//2.獲取html元素
		var htmlEle = document.documentElement;
		console.log(htmlEle);

	</script>

</body>

三、事件基礎
1.事件概述
JavaScript使我們有能力創建動態頁面,而事件是可以被JavaScript偵測到的行爲。
簡單理解:觸發——響應機制。
網頁中的每個元素都可以產生某些可以觸發JavaScript的事件,例如,我們可以在用戶點擊某按鈕時產生一個事件,然後去執行某些操作。
2.執行事件步驟
(1)獲取事件源
(2)註冊事件(綁定事件)
(3)添加事件處理機制(採取函數賦值形式)
3.常見的鼠標事件
在這裏插入圖片描述
四、操作元素
1.DOM操作可以改變網頁內容、結構和樣式,我們可以利用DOM元素來改變元素裏面的內容、屬性等。

2.改變元素內容

element.innerText

從起始到終止位置的內容,但它去除html標籤,同時空格和換行也會去掉;

element.innerHTML

起始位置到終止位置的全部內容,包括html標籤,同時保留空格和換行。

<body>
	<button id="dyz">第一張</button>
	<button id="dez">第二張</button><br>
	<img src='beauty_20200313143156.jpg'  title="這是第一張圖片">
	<script>
		//修改元素屬性
		//1.獲取元素
		var dyz = document.getElementById('dyz');
		var dez = document.getElementById('dez');
		var img = document.querySelector('img');
		//2.註冊事件  處理程序
		dez.onclick = function(){
			img.src = "beauty_20200313143213.jpg";
			img.title = "這是第二張圖片";
		}
		dyz.onclick = function(){
			img.src = "beauty_20200313143156.jpg";
			img.title = "這是第一張圖片";
		}
	</script>

</body>
<body>
	<img src="beauty_20200313143156.jpg">
	<div>上午好</div>
	<script>
		//根據系統時間不同來判斷,所以需要用到日期內置對象
		//利用多分支語句來設置不同圖片
		//需要一個圖片,並且根據時間修改圖片,就需要用到操作元素src屬性
		//需要一個div元素,顯示不同的時間問候語,修改元素內容即可
		//1.獲取元素
		var img = document.querySelector('img');
		var div = document.querySelector('div');
		//2.得到當前的小時數
		var date = new Date();
		var h = date.getHours();
		//3.判斷小時數改變圖片和文字信息
		if(h < 12){
			img.src = "beauty_20200313143156.jpg";
			div.innerHTML = '親,上午好,好好寫代碼';
		} else if(h < 18){
			img.src = "beauty_20200313143213.jpg";
			div.innerHTML = '親,下午好,好好寫代碼';
		}else {
			img.src = "IMG_20190930_204918.jpg";
			div.innerHTML = '親,晚上好,好好寫代碼';
		}
	</script>
</body>

3.表單元素的屬性操作

利用DOM可以操作如下表單元素的屬性:

type、 value、 checked、 selected、 disabled、

<body>
	<button>按鈕</button>
	<input type="text" name="" value="輸入內容">
	<script>
		//1.獲取元素
		var btn = document.querySelector('button');
		var input = document.querySelector('input');
		//2.註冊事件  處理程序
		btn.onclick = function(){
			//input.innerHTML = '點擊了';這個是普通盒子  比如 div 標籤裏面的內容
			//表單裏面的值  文字內容是通過value來修改的
			input.value = '被點擊了';
			//如果想要某個表單被禁用  不能再點擊  disabled  我們想要這個按鈕 button禁用
			// btn.disabled = true;
			this.disabled = true;
			//this 指向的是事件函數的調用者  btn
		}

	</script>
</body>

密碼框案例:

<head>
	<meta charset="utf-8">
	<title></title>
	<style>
		.box{
			position: relative;
			width: 400px;
			border-bottom: 1px solid #ccc;
			margin: 100px auto;
		}
		.box input{
			width: 370px;
			height: 30px;
			border: 0;
			outline: none;
		}
		.box img{
			position: absolute;
			top: 2px;
			right: 2px;
			width: 24px;
		}
	</style>
</head>
<body>
	<div class="box">
		<label form="">
			<img src="close.png" id="eye">
		</label>
		<input type="password" name="" id="pwd">
		
	</div>
	<script>
		//1.獲取元素
		var eye = document.getElementById('eye');
		var psw = document.getElementById('pwd');
		//2.註冊事件  處理程序
		var flag = 0;
		eye.onclick = function(){
			if(flag == 0){
			pwd.type = 'text';
			flag = 1;  //賦值操作
			eye.src = 'open.png';
		}else {
			pwd.type = 'password';
			flag = 0;
			eye.src = 'close.png';
		}
		}
	</script>
</body>

4.樣式屬性操作
我們可以通過JS修改元素大小、顏色、位置等樣式。

1.element.style 行內樣式
2.element.className 類樣式操作

注意:(1)JS裏面的樣式採取駝峯命名法,比如:fontSize、backgroundColor; (2)JS修改style樣式操作,產生的是行內樣式,css權重比較高

<style>
		div {
			width: 200px;
			height: 200px;
			background-color: pink;
		}
	</style>
</head>
<body>
	<div></div>
	<script>
		//1.獲取元素
		var div = document.querySelector('div');
		//2.註冊事件  處理程序
		div.onclick = function(){
			//div.style裏面的屬性  採取駝峯命名法
			this.style.backgroundColor = 'purple';
			this.style.width = '250px';
		}
	</script>
</body>
<style>
		.box{
			position: relative;
			width: 74px;
			height: 88px;
			border: 1px solid #ccc;
			margin: 100px auto;
			font-size: 12px;
			text-align: center;
			color: #f40;
		}
		.box img{
			width: 60px;
			margin-top: 5px;
		}
		.close-btn{
			position: absolute;
			top: -1px;
			left: -16px;
			width: 14px;
			height: 14px;
			border: 1px solid #ccc;
			line-height: 14px;
			font-family: Arial, Helvetica,sana-serif;
			cursor: pointer;
		}
	</style>
</head>
<body>
	<div class="box">
		淘寶二維碼
		<img src="code.png">
		<i class="close-btn">x</i>
	</div>
	<script>
		//1.獲取元素
		var btn = document.querySelector('.close-btn');
		var box = document.querySelector('.box');
		//2.註冊事件 處理程序
		btn.onclick = function(){
			box.style.display = 'none';
		}
	</script>
</body>
<style>
		input{
			color: #999;
		}
	</style>
</head>
<body>
	<input type="text" name="" value="手機">
	<script>
		//1.獲取元素
		var text = document.querySelector('input');
		//2.註冊事件 獲得焦點事件  onfocus
		text.onfocus = function(){
			// console.log('得到了焦點');
			if(this.value === '手機'){
				this.value = '';
			}
			//獲得焦點  需要把文本框中的文字變黑
			this.style.color = '#333';
		}
		//3.註冊事件 失去焦點事件  onblur
		text.onblur = function(){
			// console.log('失去了焦點');
			if(this.value === ''){
				this.value = '手機';
			}
			//失去焦點  顏色變淺
			this.style.color = '#999';
		} 
	</script>
</body>
<style>
		div{
			width: 150px;
			height: 150px;
			background-color: pink;
		}
		.change{
			background-color: purple;
			color: #fff;
			font-size: 25px;
			margin-top: 100px;
		}
	</style>
</head>
<body>
	<div>文本</div>
	<script>
		//1.使用element.style獲得修改元素樣式  如果樣式比較少  或者功能簡單的情況下使用
		var test = document.querySelector('div');
		test.onclick = function(){
			// this.style.backgroundColor = 'purple';
			// this.style.color = '#fff';
			// this.style.fontSize = '25px';
			// this.style.marginTop = '100px';
			//讓我們當前元素的類名等於 change
			//2.我們可以通過修改元素 的className更改元素的樣式  適用於樣式較多或者功能更復雜的情況
			this.className = 'change';
		}
	</script>
</body>

注意:
(1)如果樣式修改較多,可以採取操作類名方式更改元素樣式;
(2)class因爲是保留字,因此使用className來操作元素類名屬性;
(3)className會直接更改元素的類名,會覆蓋原先的類名。
5.自定義屬性的操作

(1)獲取屬性值
element.屬性; (獲取屬性值)
element.getAttribute(‘屬性’) ;

區別:
element.屬性; 獲取內置屬性值(元素本身自帶的屬性)
element.getAttribute(‘屬性’); 主要獲得自定義的屬性(標準)我們程序員自定義的屬性

(2)設置屬性值
element.屬性 = ‘值’; 設置內置屬性
element.setAttribute(‘屬性’,‘值’);

(3)移除屬性
element.removeAttribute(‘屬性’);

6.H5自定義屬性
自定義屬性的目的:是爲了保存並使用數據,有些數據可以保存到頁面中而不用保存到數據庫中。

自定義屬性獲得通過getAttribute(‘屬性’)獲取;但是有些自定義屬性很容易引起歧義,不容易判斷是元素的內置屬性還是自定義屬性。H5給我們新增了自定義屬性:

(1)設置H5自定義屬性
H5規定自定義屬性data-開頭:
比如:

<div data-index = "1"></div>

或者使用JS設置

element.setAttribute('data-index', 2);

(2)獲取H5自定義屬性

1.兼容性獲取:element.getAttribute(‘data-index’)
2.H5新增element.dataset.index 或者
element.dataset[‘index’] ie11以上

<body>
	<div getTime = "20" data-index = "2" data-list-name = "andy"></div>
	<script>
		var div = document.querySelector('div');
		console.log(div.getAttribute("getTime"));
		div.setAttribute('data-time', 20);
		console.log(div.getAttribute('data-index'));
		console.log(div.getAttribute('data-list-name'));
		//h5新增  他只能獲取data- 開頭的
		//dataset是一個集合,裏面存放了所有以data開頭的自定義屬性
		console.log(div.dataset);
		console.log(div.dataset.index);
		//如果自定義屬性裏面有多個-連接的單詞,我們獲取的時候採取  駝峯命名法
		console.log(div.dataset.listName);
		
	</script>
</body>

7.節點操作

a.獲取元素通常使用兩種方式:
(1)利用DOM提供的方法獲取元素
document.getElementById()
document.getElementsByTagName()
document.querySelector()等,
缺點:繁瑣、沒有邏輯性
(2)利用節點層級關係獲取元素
利用父子兄弟節點關係獲取元素
邏輯性強,但是兼容性稍差

b.節點概述
一般地,節點至少擁有nodeType(節點類型)、nodeName(節點名稱)和nodeValue(節點值)這三個基本屬性。

元素節點nodeType爲1

屬性節點nodeType爲2

文本節點nodeType爲3(文本節點包含文字、空格、換行符)
實際開發中,節點操作主要操作的是元素節點

c.節點層級
常見的是父子兄層級關係

(1)父級節點

node.parentNode

(2)子節點

parentNode.childNodes(標準):拿到的是所有子節點, 包含元素節點 文本節點等等;實際開發中不提倡

parentNode.children(非標準):但是得到了各個瀏覽器的支持,因此可以放心使用

parentNode.firstChild:firstChild返回第一個子節點,找不到則返回null,同樣,也是包含所有節點

parentNode.lastChild:返回最後一個子節點,找不到則返回null,同樣,也是包含所有節點

parentNode.firstElementChild和parentNode.lastElementChild都返回的是元素節點,找不到則返回null, 這兩個方法都有兼容性問題,IE9以上才支持。

<body>
	<ol>
		<li>我是li1</li>
		<li>我是li2</li>
		<li>我是li3</li>
		<li>我是li4</li>
	</ol>
	<script>
		var ol = document.querySelector('ol');
		//1.fistChild 獲取的是第一個子節點  不管是文本節點還是元素節點
		console.log(ol.firstChild);
		console.log(ol.lastChild);
		//2.firstElementChild  返回第一個元素節點
		console.log(ol.firstElementChild);
		console.log(ol.lastElementChild);
		//3.實際開發的寫法,既沒有兼容性問題又返回第一個子元素
		console.log(ol.children[0]);
		console.log(ol.children[ol.children.length - 1]);
	</script>
</body>

(3)兄弟節點

node.nextSibling: 返回當前元素的下一個兄弟節點,找不到返回Null,同樣包含所有節點

node.prexiousSibling:返回當前元素的上一個兄弟節點,找不到返回Null,同樣包含所有節點

node.nextElementSibling: 返回當前元素的下一個兄弟元素節點,找不到返回Null

node.prexiousElementSibling:返回當前元素的上一個兄弟節點,找不到返回Null

node.nextElementSibling和node.prexiousElementSibling都存在兼容性問題,IE9以上才支持

<body>
	<div>我是div</div>
	<span>我是span</span>
	<script>
		var div = document.querySelector('div');
		//1.nextSibling 下一個兄弟節點  包含元素節點和文本節點
		console.log(div.nextSibling);
		console.log(div.previousSibling);
		//2.nextElementSibling  得到下一個兄弟節點
		console.log(div.nextElementSibling);
		console.log(div.previousElementSibling);
	</script>
</body>

解決方法:封裝一個兼容性的函數;

function getNextElementSibling(element) {
            var el = element;
            while (el = el.nextElementSibling) {
                if (el.nodeType === 1) {
                    return el;
                }
            }
            return null}

(4)創建節點

document.createElement(‘tagName’)

document.createElement(‘tagName’)方法創建由tagName指定的的HTML元素,因爲這些元素原先不存在,是根據我們的需求動態生成的,所以我們也稱爲動態創建元素節點。

(5)添加節點

node.appendChild(child)

node.appendChild()方法將一個節點添加到指定父節點的子節點列表末尾,類似於css裏面的after僞元素。

<body>
    <ul>
        <li>123</li>
    </ul>
    <script>
        //1.創建節點
        var li = document.createElement('li');
        //2.添加節點  node.appendChild(Child)  node是父級  child 是子集  後面追加元素 類似於數組的push
        var ul = document.querySelector('ul');
        ul.appendChild(li);
        //3.添加節點  node.insertBefore(child, 指定元素)
        var lili = document.createElement('li');
        ul.insertBefore(lili, ul.children[0]);
        //4.我們先要頁面添加一個新的元素:1.創建元素 2.添加元素
    </script>
</body>

簡單留言發佈:

<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<title></title>
	<style>
		textarea{
			width: 100px;
			height: 100px;
		}
		ul li{
			background-color: pink;
			width: 300px;
			margin-top: 5px;
		}
	</style>
</head>
<body>
	<textarea name="" id=""></textarea>
	<button>發佈</button>
	<ul>
		
	</ul>
	<script>
		//1.獲取元素
		var btn = document.querySelector('button');
		var text = document.querySelector('textarea');
		var ul =  document.querySelector('ul');	
		//2.註冊事件
		btn.onclick = function(){
			if(text.value == ''){
				alert('你沒有輸入內容!!!')
				return false;
			}else{
				// console.log(text.value);
				//(1)創建元素
			var li = document.createElement('li');
			//先有 li  才能賦值
			li.innerHTML = text.value;
			//(2)添加元素
			ul.insertBefore(li,ul.children[0]);
			}
			
		}
	</script>
</body>
</html>

效果圖:
在這裏插入圖片描述
(6)刪除節點

node.removeChild(child)

node.removeChild()方法從DOM中刪除一個子節點,返回刪除的節點。

<!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>
    <button>刪除</button>
    <ul>
        <li>熊大</li>
        <li>熊二</li>
        <li>光頭強</li>
    </ul>
</body>
<script>
    //1.獲取元素
    var ul = document.querySelector('ul');
    var btn = document.querySelector('button');
    //2.刪除元素
    // ul.removeChild(ul.children[0]);
    //3.點擊按鈕依次刪除裏面的子節點
    btn.onclick = function() {
        if (ul.children.length == 0) {
            this.disabled = true;
        } else {
            ul.removeChild(ul.children[0]);
        }

    }
</script>

</html>

(6)複製節點(克隆節點)

node.cloneNode()

node.cloneNode()方法返回調用該方法的節點的一個副本,也稱爲克隆節點/拷貝節點

注意:
1.如果括號裏面參數爲空或者false,則是淺拷貝,即只是克隆複製節點本身,不克隆裏面的子節點(內容)。
2.如果括號裏面爲true,則是深拷貝,會複製節點本身及其裏面的所有子節點

動態創建刪除表格案例:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        table {
            width: 500px;
            margin: 100px auto;
            border-collapse: collapse;
            text-align: center;
        }
        
        td,
        th {
            border: 1px solid #333;
        }
        
        thead tr {
            height: 40px;
            background-color: #ccc;
        }
    </style>
</head>

<body>
    <table cellspacing="0">
        <thead>
            <tr>
                <th>姓名</th>
                <th>科目</th>
                <th>成績</th>
                <th>操作</th>
            </tr>
        </thead>
        <tbody>

        </tbody>
    </table>
    <script>
        //1.準備數據
        var datas = [{
            name: '張三',
            subject: 'javascript',
            score: 100
        }, {
            name: '李四',
            subject: 'javascript',
            score: 90
        }, {
            name: '王五',
            subject: 'javascript',
            score: 95
        }, {
            name: '王七',
            subject: 'javascript',
            score: 89
        }];
        //2.tbody中創建行:有幾個人就創建幾行,通過數組長度得到
        var tbody = document.querySelector('tbody');
        for (var i = 0; i < datas.length; i++) { //外面的for循環管行數
            //創建行
            var tr = document.createElement('tr');
            tbody.appendChild(tr);
            //行裏面創建單元格 td  單元格數量取決於每個對象裏面的屬性個數
            //for循環遍歷對象
            for (var k in datas[i]) { //裏面的單元格管列數
                var td = document.createElement('td');
                //把對象裏面的屬性值給 td
                console.log(datas[i][k]);
                td.innerHTML = datas[i][k];
                tr.appendChild(td);
            }
            //3.創建有刪除2個字的單元格
            var td = document.createElement('td');
            td.innerHTML = '<a href = "javascript:;">刪除</a>';
            tr.appendChild(td);
        }
        //4.刪除操作
        var as = document.querySelectorAll('a');
        for (var i = 0; i < as.length; i++) {
            as[i].onclick = function() {
                //點擊a  刪除當前a所在的行  node.removeChild(child)
                tbody.removeChild(this.parentNode.parentNode);
            }
        }
    </script>
</body>

</html>

五、三種動態創建元素的區別

  • documen.write()
  • document.innerHTML
  • document.createElement()

區別:

1.document.write是直接將內容寫入頁面流,但是文檔流執行完畢,則它會導致頁面重繪

2.innerHTML是將內容寫入某個DOM節點,不會導致頁面全部重繪

3.innerHTML創建多個元素效率更高(不要拼接字符串,採取數組形式拼接),結構稍微復

4.createElement()創建多個元素效率稍低一點點,但是結構清晰。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章