JavaScript進階內容——DOM詳解

2022-07-21 12:03:50

JavaScript進階內容——DOM詳解

當我們已經熟練掌握JavaScript的語法之後,我們就該進入更深層次的學習了

首先我們思考一下:JavaScript是用來做什麼的?

  • JavaScript誕生就是為了能夠讓它在瀏覽器中執行

那麼DOM就是我們學習中不可或缺的一個環節,下面讓我們深入瞭解DOM

DOM簡介

DOM定義:

  • 檔案物件模型(DOM),是W3C組織推薦的處理可延伸標示語言(HTML或者XML)的標準程式設計介面

DOM作用:

  • 用來修改網頁內容,結構和樣式

DOM樹:

  • 我們用一個圖片來表示(來自B站黑馬程式設計師Pink老師)

獲得元素

DOM在我們實際開發中主要用來操作元素

那麼如果要操作元素,最基本的就是要先獲得元素:

  1. ID獲得元素:

程式碼:

//注意這裡返回的是元素物件
document.getElementById('ID');

案例展示:

<!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"></div>


<script>
    //1.我們常常把script放在body的內部下方
    //2.get 獲得 Element 元素 by 通過 Id
    //3.注意ID是大小寫敏感
    //4.返回的是一個元素物件
    var div1 = document.getElementById('div1');
    //這裡正常輸出
    console.log(div1);
    //這裡dir表示更好的輸出(展示其整體內容)
    console.dir(div1);
</script>
</body>
</html>
  1. 標籤名獲取元素:

程式碼:

//注意這裡返回的是元素物件集合
document.getElementsByTagName('TagName');
//可以獲得某個父元素中的全部元素物件集合
element.getElementsByTagName('TagName');

案例展示:

<!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>
    <ul>
        <li>1</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
        <li>5</li>
    </ul>

    <ol id="ol">
        <li>1</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
        <li>5</li>
    </ol>

    <script>
        //這裡是整個body中的li,返回的是元素物件集合
        var lis = document.getElementsByTagName('li');
        console.log(lis);
        //通過遍歷獲得集合中各個元素物件
        for (const iterator of lis) {
            console.log(iterator);
        }

        //當li為空,仍舊返回陣列,但為空陣列(偽陣列)

        //我們可以單獨獲得ol中的li
        var ol = document.getElementById('ol');
        var ollis = ol.getElementsByTagName('li');
        //通過遍歷獲得集合中各個元素物件
        for (const iterator of ollis) {
            console.log(iterator);
        }
    </script>
</body>
</html>
  1. 類名獲取元素(HTML5):

程式碼:

document.getElementByClassName('類名');

案例展示:

<!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="nav"></div>
    <div class="box"></div>
    <div class="box">
        <ul>
            <li></li>
            <li></li>
        </ul>
    </div>

    <script>
        //1.通過類名獲得物件
        var box = document.getElementsByClassName('div');
        console.log(box);

        //2.document.querySelector('.box')我們可以獲得選擇器中的第一個
        var fristBox = document.querySelector('.box');

        //3。上方的獲取方法同樣適用於id選擇,注意需要用‘’包括
        var nav = document.querySelector('#nav');

        //4.同樣使用於標籤選擇
        var fristLi = document.querySelector('li');

        //5.document.querySelectorAll()獲取所有的型別的集合
        var allLi = document.querySelectorAll('li');
    </script>
</body>
</html>
  1. 獲得特殊標籤body和html元素

程式碼:

//body元素
document.body
//html元素
document.documentElement

案例展示:

<!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>
    

    <script>
        //1.獲得body元素
        var bodyEle = document.body;
        console.log(bodyEle);
        console.dir(bodyEle);

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

事件基礎

JavaScript使我們有能力建立動態頁面,而事件就是被JavaScript所偵測到的行為。

頁面中的每個元素都可以產生某些觸發JavaScript的事件,簡單來說就是產生:觸發——響應機制

事件三要素

我們把事件分為三部分:

  • 事件源
    • 事件被觸發的物件
  • 事件型別
    • 如何觸發,例如點選onclick
  • 事件處理程式
    • 通過一個函數賦值的方法完成

我們下面給出基本格式:

name.methodName = function() {
    ~~~
    ~~~
}

我們給出一個基礎案例:

<!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>
    <button id="but">按鈕</button>

    <script>
        //我們下面做出的:點選按鈕就會彈出「你好」的對話方塊
        
        //1.獲得事件源
        var button = document.getElementById('but');
        //2.針對事件源,給出事件型別和事件處理程式(這裡指點選事件)
        button.onclick = function() {
            alert("你好");
        }
    </script>
</body>
</html>

事件型別概括

我們下面給出所有可用到的事件型別:

滑鼠事件 觸發條件
onclick 滑鼠點選左鍵觸發
onmouseover 滑鼠經過觸發
onmouseout 滑鼠離開觸發
onfocus 獲得滑鼠焦點觸發
onblur 失去滑鼠焦點觸發
onmousemove 滑鼠移動觸發
onmouseup 滑鼠彈起觸發
onmousedown 滑鼠按下觸發

操作元素

我們學習事件的目的就是為了對元素進行修改

下面我們依次介紹一些操作元素的方法:

元素內容修改

元素內容修改有兩種方法:

//element.innerText不識別HTML標籤,會去除空格和換行
element.innerText = '';
//element.innerHTML識別HTML標籤,不會去除空格和換行(推薦)
element.innerHTML = '';
//注意:我們可以通過上述方法來獲得該元素的內容

除內容修改外,元素屬性同樣也可以進行修改:

//我們需要把下述圖片修改放於某元素的事件中就可以進行修改
img.src = '';

案例展示:

<!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>
    <button id="but">按鈕</button>
    <div class="box">時間~~~~</div>

    <script>
        //當我們點選按鈕,將box內容更改為當前時間

        //獲得元素
        var button = document.getElementById('but');
        var timer = document.querySelector(".box");

        //做出事件
        button.onclick = function() {
            //注意這裡採用innerHTML,strong會以HTML的形式用來加粗內容而不會展示出來
            timer.innerHTML = "<strong>2022.7.20</strong>";
        }
    </script>
</body>
</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>
    <button id="ldh">劉德華</button>
    <button id="zxy">張學友</button>
    <img src="images/ldh.jpg">

  • 事件冒泡:IE最早提出,事件開始時由具體的元素接收,然後逐級向上傳播到DOM最頂層節點的過程
  • 事件捕獲:網景最早提出,由DOM最頂層節點開始,然後逐層向下傳播到最具體的元素接收過程

我們通過一些程式碼來解釋:

<!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>
    <style>
        .father {
            height: 400px;
            width: 400px;
            background-color: pink;
        }

        .son {
            height: 200px;
            width: 200px;
            background-color: purple;
            margin: auto;
        }
    </style>
</head>
<body>
    <div class="father">
        <div class="son">son</div>
    </div>

    <script>
        var son = document.querySelector('.son');

        // 注意:下述程式碼具有互斥性,測試時請先註釋掉其中一部分

        // 注意:JS程式碼中只能執行捕獲或者冒泡的其中一個階段
        // 注意:onclick只能得到冒泡階段,要研究捕獲階段,需要採用addEventListener,且第三個引數為true時,屬於捕獲階段
        // 捕獲階段: document-> html -> body -> father -> son
        // 冒泡階段: son -> father -> body -> html -> document

        // 首先先來解釋捕獲
        // 當我們對他們均設定function方法,當執行一個底部物件的函數,我們需要按照順序先執行上方的函數
        // 例如:下面的程式碼,當我們點選son,會先輸出father的2,再輸出son的1
        
        son.addEventListener('click',function(){
            alert('1');
        },true);
        son.parentNode.addEventListener('click',function(){
            alert('2');
        },true);

        // 對於冒泡也是同理
        // 我們執行底層物件的函數時,需要按照順序先從下面的函數執行,然後逐漸執行上面的函數

        son.addEventListener('click',function(){
            alert('1');
        });
        son.parentNode.addEventListener('click',function(){
            alert('2');
        });
    </script>
</body>
</html>

事件物件

首先我們先來介紹一下事件物件:

  • 事件物件是指 事件函數的引數
  • 它通常用e,evt,event來命名
  • 事件物件不需要傳遞,是系統自動生成的
  • 事件物件包含了跟事件有關的一系列資訊資料,它是一個集合,包含許多屬性和方法

案例展示:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=, initial-scale=1.0">
    <title>Document</title>
    <style>
        div {
            height: 400px;
            width: 400px;
            background-color: pink;
        }
    </style>
</head>
<body>
    <div></div>
    <div></div>

    <script>
        var divs = document.querySelectorAll('div');

        // function中的引數event就是事件物件
        // 不需要傳遞引數,是系統自動形成,可以任意命名
        divs[0].onclick = function (event) {
            // 我們可以檢視event所包含的內容
            console.log(event);
        }

        // 使用addEventListener方法 以及 其他操作也是可以的
        // 滑鼠就會展示滑鼠相關資訊,鍵盤就會展示鍵盤相關資訊
        divs[1].addEventListener('mouseover',function(event){
            console.log(event);
        })
    </script>
</body>
</html>

下面我們介紹一下常見事件物件的屬性和方法:

事件物件屬性方法 說明
e.target 返回觸發事件的物件 標準
e.srcElement 返回觸發事件的物件 非標準 ie6~ie8使用
e.type 返回事件的型別,比如click,mouseover
e.cancelBubble 該屬性阻止冒泡 非標準 ie6~ie8使用
e.returnValue 該屬性 阻止預設事件(預設行為)非標準 ie6~ie8使用 比如不讓連結跳轉
e.preventDefault() 該屬性 阻止預設事件(預設行為)標準 比如不讓連結跳轉
e.stopPropagation() 阻止冒泡 標準

下面我們用程式碼形式分開介紹一些屬性和方法:

  • e.target和this的區別:

    <!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>
        <style>
            div {
                height: 300px;
                width: 300px;
                background-color: pink;
            }
        </style>
    </head>
    <body>
        <div>111</div>
        <ul>
            <li>1</li>
            <li>2</li>
            <li>3</li>
        </ul>
    
        <script>
            var div = document.querySelector('div');
    
            // 首先我們介紹一下target
            div.onclick = function(e) {
                // target是指觸發該事件的物件,即你點選哪裡就是哪個物件觸發
                console.log(e.target);
            }
    
            // 然後我們稍微區別一下this
            // this永遠只是指呼叫物件本體
            var ul = document.querySelector('ul');
            ul.addEventListener('click',function(e){
                // 這裡this指向的永遠是ul
                console.log(this);
                // 這裡target,當你點選的是li時,返回的物件是li
                console.log(e.target);
            })
        </script>
    </body>
    </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>123</div>
    <a href="https://www.baidu.com/">百度</a>
    <form action="https://www.baidu.com/">
        <input type="submit" value="提交" name="sub">
    </form>

    <script>
        var div = document.querySelector('div');
        var a = document.querySelector('a');
        var input = document.querySelector('input');


        // 我們在這裡稍微介紹一下type屬性
        // 首先我們設定一個函數
        fn = function(e) {
            console.log(e.type);
        }
        // 然後我們把這個函數應用到某些物件的某些操作中
        div.addEventListener('click',fn);
        div.addEventListener('mouseover',fn);
        div.addEventListener('mouseout',fn);

        // 接下來我們介紹阻止預設行為:e.preventDefault()方法
        // 正常情況下我們點選連線會進行跳轉,我們點選提交按鈕會進行資訊提交
        // 但是當我們採用了阻止預設行為,我們的這些行為就會被組織

        // 採用e的方法來阻止預設行為
        a.addEventListener('click',function(e){
            // 注意是方法,需要帶()
            e.preventDefault();
        })
        // 我們也可以採用return false來阻止預設行為
        input.onclick = function(e){
            // 注意return方法只能在傳統方法中使用,在addEventListener中無法使用
            return false;
        }
    </script>
</body>
</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>
    <style>
        .father {
            height: 400px;
            width: 400px;
            background-color: pink;
        }

        .son {
            height: 200px;
            width: 200px;
            background-color: purple;
            margin: auto;
        }
    </style>
</head>
<body>
    <div class="father">
        <div class="son">son</div>
    </div>

    <script>
        var son = document.querySelector('.son');

        // 當我們採用stopPropagation時,冒泡不再進行

        son.addEventListener('click',function(e){
            alert('1');
            // 我們對son進行冒泡禁止處理,當點選son時僅對son的函數輸出
            e.stopPropagation();
        });
        son.parentNode.addEventListener('click',function(){
            alert('2');
            // 我們未對father進行冒泡禁止處理,所以點選father時,document的函數alert('3')仍會輸出
        });
        son.parentNode.parentNode.addEventListener('click',function(){
            alert('3');
        });
    </script>
</body>
</html>

事件委託

事件委託解釋:

  • 事件委託被稱為時間代理,在jQuery中被稱為事件委派

事件委託原理:

  • 不在每個子節點單獨設定事件監聽器,而是將事件監聽器設定在其父節點上,然後利用冒泡原理影響設定每個子節點

事件委託的作用:

  • 我們僅需要操作一次DOM,提高了程式的效能

案例解釋:

<!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>
    <ul>
        <li>點選我彈出彈框</li>
        <li>點選我彈出彈框</li>
        <li>點選我彈出彈框</li>
        <li>點選我彈出彈框</li>
        <li>點選我彈出彈框</li>
    </ul>

    <script>
        // 將事件監聽器設定在其父節點上,然後利用冒泡原理影響設定每個子節點

        var ul = document.querySelector('ul');

        ul.addEventListener('click',function(e){
            // 當點選時,彈出彈框
            alert('彈框');
            // 我們也可以針對點選的物件來進行一些操作
            e.target.style.backgroundColor = 'black';

        })
    </script>
</body>
</html>

滑鼠事件拓展

我們在前面給出了一些滑鼠操作:

滑鼠事件 觸發條件
onclick 滑鼠點選左鍵觸發
onmouseover 滑鼠經過觸發
onmouseout 滑鼠離開觸發
onfocus 獲得滑鼠焦點觸發
onblur 失去滑鼠焦點觸發
onmousemove 滑鼠移動觸發
onmouseup 滑鼠彈起觸發
onmousedown 滑鼠按下觸發

下面我們再介紹一些另類的滑鼠事件:

  • 禁止右鍵選中:

    document.addEventListener('contextmenu',function(e){
        //禁止contextmenu右鍵滑鼠操作
    	e.preventDefault();
    })
    
  • 禁止選中文字:

    document.addEventListener('selectstart',function(e){
        //禁止selectstart選中文字
    	e.preventDefault();
    })
    

滑鼠事件物件

event物件代表事件的狀態,跟事件相關的一系列資訊的集合

我們首先來學習滑鼠事件物件:

滑鼠屬性 說明
e.clientX 當前可視頁面的x
e.clientY 當前可視頁面的y
e.pageX 當前頁面的x(不具有相容性)
e.pageY 當前頁面的y(不具有相容性)

程式碼範例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=, initial-scale=1.0">
    <title>Document</title>
    <style>
        body {
            height: 3000px;
        }
    </style>
</head>
<body>
    
    <script>
        // 接下里都是滑鼠物件的屬性

        // 這裡表示在頁面內點選時
        // 注意只能用addEventListener,傳統方法不能使用
        document.addEventListener('click',function(e){
            // 這裡獲得的是針對當前可視頁面的x,y
            console.log(e.clientX);
            console.log(e.clientY);

            // 分割線
            console.log('------------------')

            // 這裡獲得的是針對當前頁面的x,y(針對IE9以上版本)
            console.log(e.pageX);
            console.log(e.pageY);
        })
    </script>
</body>
</html>

鍵盤事件和鍵盤事件物件

我們先來學習鍵盤事件:

鍵盤事件 說明
onkeyup 某個鍵盤按鍵被鬆開時觸發
onkeydown 某個鍵盤按鍵被按下時觸發
onkeypress 某個鍵盤按鍵被按下時觸發(不能識別功能鍵,如ctrl,shift,左右箭頭)

注意:

  • 三個時間的執行順序:keydown -> keypress -> keyup

然後我們來了解一下鍵盤事件物件:

鍵盤事件物件屬性 說明
e.key 返回相應鍵(不具備相容性,不推薦)
e.keyCode 返回相應鍵的ASCII值(具有相容性,推薦)

注意:

  • keyup和keydown事件中不區分大小寫,均為大寫輸出
  • keypress事件區分大小寫,A:65,a:97

案例展示:

<!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>
    <script>
        // 下述都是針對頁面操作:
        document.addEventListener('keyup',function(){
            console.log('彈起')
        })
        document.addEventListener('keydown',function(){
            console.log('按下down')
        })
        document.addEventListener('keypress',function(){
            console.log('按下press')
        })

        // 接下來我們講解一下keyCode:
        // 注意:keydown不區分大小寫,keypress區分大小寫
        document.addEventListener('keydown',function(e){
            console.log('down:' + e.keyCode);
        })
        document.addEventListener('keypress',function(e){
            console.log('press:' + e.keyCode);
        })
    </script>
</body>
</html>

結束語

好的,那麼關於DOM的全部知識點總結完畢!

下一節我會對BOM做出詳解,並且在JavaScript的內容結束後,會對DOM的各種實際網頁應用做出各種案例模板,請多多關照!