js學習筆記——(11)DOM事件高級(DOM事件對象、阻止事件冒泡、鼠標事件、鍵盤事件)

一、註冊事件(綁定事件)

1.1註冊事件概述

給元素添加事件,稱爲註冊事件或者綁定事件。
註冊事件有兩種方式:傳統方式和方法監聽註冊方式。

傳統註冊方式

  • 利用on開頭事件onclick
  • 特點:註冊事件的唯一性
  • 同一個元素同一個事件只能設置一個處理函數,最後註冊的處理函數將會覆蓋前面註冊的處理函數。

方法監聽註冊方式

  • W3C標準推薦方式
  • addEventListener()它是一個方法
  • IE9之前的IE不支持此方法,可以使用attachEvent()代替
  • 特點:同一個元素同一個事件可以註冊多個監聽器
  • 按照註冊事件依次執行

1.2addEventListener事件監聽方式

eventTarget.addEventListener(type, listener[, useCapture])

eventTarget.addEventListener()方法將指定的監聽器註冊到eventrarget (目標對象)上,當該對
象觸發指定的事件時,就會執行事件處理函數。
該方法接收三個參數:

  • type :事件類型字符串,比如click、mouseover , 注意這裏不要帶on
  • listener :事件處理函數,事件發生時,會調用該監聽函數
  • useCapture: 可選參數,是-個布爾值,默認是false

1.3attachEvent 事件監聽方式(IE9以下)

eventTarget . att achEvent (eventNamewi thon,callback)
eventrarget . attachEvent ()方法將指定的監聽器註冊到eventrarget (目標對象)上,當該對象觸
髮指定的事件時,指定的回調函數就會被執行。
該方法接收兩個參數:

  • eventNameWithOn :事件類型字符串,比如onclick. onmouseover, 這裏要帶 on
  • callback :事件處理函數,當目標觸發事件時回闊函數被調用

1.4註冊事件兼容性解決方案

function addEventListener (element, eventName, fn) {
//判斷當前瀏覽器是否支持addEventListener方法
	if (element.addEventListener) {
		element.addEventListener (eventName, fn); // 第三個參數默認是false
	} else if (element.attachEvent) {
		element.attachEvent('on' + eventName,fn);
	} else {
//相當於element .οnclick= fn;
	element[ 'on' + eventName] = fn;
	}
}
<!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>
    <button>方法監聽註冊事件</button>
    <button>IE9</button>

    <script>
        //1.傳統方式註冊事件
        var btns = document.querySelectorAll('button');
        btns[0].onclick = function() {
            alert('hi');
        }
        btns[0].onclick = function() {
                alert('hello');
            }
            //2.事件偵聽註冊事件  addEventListener裏面的事件類型是字符串  必定加引號  而且不帶on
        btns[1].addEventListener('click', function() {
            alert(22);
        })
        btns[1].addEventListener('click', function() {
                alert(33);
            })
            //3.attachEvent  ie9以前版本
        btns[2].attachEvent('onclick', function() {
            alert(11);
        })
    </script>
</body>

</html>

二、刪除事件

2.2刪除事件的方式

1.傳統註冊方式

eventTarget.onclick = null;

2.方法監聽註冊方式

eventTarget.removeEventListener(Type, listener[, useCapture])

<!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>
        div {
            width: 100px;
            height: 100px;
            background-color: pink;
        }
    </style>
</head>


<body>
    <div>1</div>
    <div>2</div>
    <div>3</div>
</body>
<script>
    var divs = document.querySelectorAll('div');
    divs[0].onclick = function() {
            alert(11);
            //1.傳統方式刪除事件
            divs[0].onclick = null;
        }
        //2.removeEventListener  刪除事件
    divs[1].addEventListener('click', fn); //裏面的fn不需要調用加小括號

    function fn() {
        alert(22);
        divs[1].removeEventListener('click', fn);
    }
    //3.
    divs[3].attachEvent('onclick', fn1);

    function fn1() {
        alert(33);
        div[2].detattachEvent('onclick', fn1);
    }
</script>

</html>

三、DOM事件流

事件流描述的是從頁面中接收事件的順序

事件發生時會在元素節點之間按照待定的順序傳播,這個傳播過程即DOM事件流

DOM事件流分爲3個階段:

1.捕獲階段

2.當前目標階段

3.冒泡階段
在這裏插入圖片描述
事件冒泡:IE最早提出,事件開始時由最具體的元素接收,然後逐級向上傳播到DOM最頂層節點的過程

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

在這裏插入圖片描述
注意:

(1)JS代碼中只能執行捕獲或者冒泡其中的一個階段
(2)onclick和attachEvent只能得到冒泡階段
(3)addEventListener(type, listener, [, useCapture])第三個參數如果是true,表示在事件捕獲階段調用事件處理程序,如果是false(不寫就默認爲false),表示在事件冒泡階段調用事件處理程序。
(4)實際開發中我們很少使用捕獲事件,我們更關注事件冒泡
(5)有些事件是沒有冒泡的,比如onblur、onfocus、onmouseenter、onmouseleave

<!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>
        .father {
            overflow: hidden;
            width: 400px;
            height: 400px;
            margin: 100px auto;
            background-color: pink;
            text-align: center;
        }
        
        .son {
            width: 300px;
            height: 300px;
            margin: 50px;
            background-color: purple;
            line-height: 300px;
            color: #fff;
        }
    </style>
</head>

<body>
    <div class="father">
        <div class="son">son盒子</div>
    </div>
    <script>
        //捕獲階段  如果 addEventListener  第三個參數是 true 那麼處於捕獲階段
        //body -> father -> son
        // var son = document.querySelector('.son');
        // son.addEventListener('click', function() {
        //     alert('son');
        // }, true);
        // var father = document.querySelector('.father');
        // father.addEventListener('click', function() {
        //     alert('father');
        // }, true);
        //冒泡階段
        var son = document.querySelector('.son');
        son.addEventListener('click', function() {
            alert('son');
        });
        var father = document.querySelector('.father');
        father.addEventListener('click', function() {
            alert('father');
        });
        document.addEventListener('click', function() {
                alert('document');
            })
    </script>
</body>

</html>

四、事件對象

4.1什麼是事件對象?

eventTarget. onclick = function (event) {}
eventTarget . addEventListener(‘click’, function(event) {})

這個event就是事件對象,我們還喜歡的寫成e或者evt

官方解釋: event對象代表事件的狀態,比如鍵盤按鍵的狀態鼠標的位置、鼠標按鈕的狀態。
**簡單理解:**事件發生後,跟事件相關的一系列信息數據的集合都放到這個對象裏面,這個對象就是事件對象event ,它有很多屬性和方法。

比如:①誰綁定了這個事件②鼠標觸發事件的話,會得到鼠標的相關信息,如鼠標位置③鍵盤觸發事件的話,會得到鍵盤的相關信息,如按了哪個鍵

這個event是個形參,系統幫我們設定爲事件對象,不需要傳遞實參過去,當我們註冊事件時,event對象就會被系統自動創建,並依次傳遞給事件監聽器(事件處理函數)

4.2事件對象兼容性方案

事件對象本身的獲取存在兼容問題:
1.標準瀏覽器中是瀏覽器給方法傳遞的參數,只需要定義形參e就可以獲取到。
2.在IE6~8中,瀏覽器不會給方法傳遞參數,如果需要的話,窩要到window.event中獲取查找。

<!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>
    <div>123</div>
    <script>
        //1.event就是一個事件對象  寫到我們偵聽函數的小括號裏 當形參來看
        //2.事件對象只有有了事件纔會存在,它是系統給我們自動創建的 不需要我們傳遞參數
        //3.事件對象是我們事件的一系列相關數據的集合 跟事件相關的 比如鼠標點擊裏面就包含了鼠標的相關信息,
        //鼠標座標,如果是鍵盤事件裏面就包含的鍵盤事件的信息  比如判斷用戶按下了哪個鍵
        //4.這個事件對象我們可以自己命名  比如 event evt e
        //5.事件對象也有兼容性問題 IE678通過window.event
        var div = document.querySelector('div');
        // div.onclick = function(event) {

        //     console.log(event);

        // }
        div.addEventListener('click', function(e) {
            console.log(e);
        })
    </script>
</body>

</html>

4.3事件對象的常見屬性和方法

在這裏插入圖片描述
五、阻止冒泡事件

5.1阻止事件冒泡的兩種方式

事件冒泡:開始時由最具體的元素接收,然後逐級向上傳播到DOM的最頂層節點

阻止事件冒泡

  • 標準寫法:利用事件對象裏面的stopPropagation()方法
  • 非標準寫法:IE 678利用事件對象cancelBubble屬性

5.2阻止事件冒泡的兼容性解決方案

  if (e && e.stopPropagation){
            e.stopPropagation;
  }else{
            window.event.cancelBubble = 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>
        .father {
            overflow: hidden;
            width: 400px;
            height: 400px;
            margin: 100px auto;
            background-color: pink;
            text-align: center;
        }
        
        .son {
            width: 300px;
            height: 300px;
            margin: 50px;
            background-color: purple;
            line-height: 300px;
            color: #fff;
        }
    </style>
</head>

<body>
    <div class="father">
        <div class="son">son盒子</div>
    </div>
    <script>
        //捕獲階段  如果 addEventListener  第三個參數是 true 那麼處於捕獲階段
        //body -> father -> son
        // var son = document.querySelector('.son');
        // son.addEventListener('click', function() {
        //     alert('son');
        // }, true);
        // var father = document.querySelector('.father');
        // father.addEventListener('click', function() {
        //     alert('father');
        // }, true);
        //冒泡階段
        var son = document.querySelector('.son');
        son.addEventListener('click', function(e) {
            alert('son');
            e.stopPropagation();
            e.cancelBubble = true;
        });
        var father = document.querySelector('.father');
        father.addEventListener('click', function() {
            alert('father');
        });
        document.addEventListener('click', function() {
                alert('document');
            })
            //兼容性解決方案
            // if (e && e.stopPropagation){
            //     e.stopPropagation;
            // }else{
            //     window.event.cancelBubble = true;
            // }
    </script>
</body>

</html>

六、事件委託(代理、委託)

事件委託

事件委託也稱爲事件代理,在jQuery裏面稱爲事件委派

事件委託的原理

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

事件委託作用

我們只操作了一次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>
    <ul>
        <li>彈框</li>
        <li>彈框</li>
        <li>彈框</li>
        <li>彈框</li>
        <li>彈框</li>
    </ul>
    <script>
        var ul = document.querySelector('ul');
        var lis = document.querySelectorAll('li');
        ul.addEventListener('click', function(e) {
            // alert('彈框');
            for (var i = 0; i < lis.length; i++) {
                lis[i].style.backgroundColor = '';
                e.target.style.backgroundColor = 'pink';
            }

        })
    </script>
</body>

</html>

七、常用的鼠標事件

7.1常用的鼠標事件
在這裏插入圖片描述

1.禁止鼠標右鍵菜單

contextmenu主要控制應該何時顯示上下文菜單,主要用於程序員取消默認的上下文菜單

document.addEventListener('contextmenu', function(e){
		e.preventDefault();
})

2.禁止鼠標選中(selectstart 開始選中)

<!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>
        //1.contextmenu  我們可以禁用右鍵菜單
        document.addEventListener('contextmenu', function(e) {
                e.preventDefault();
            })
            //2.禁止選中文字
        document.addEventListener('selectstart', function(e) {
            e.preventDefault();
        })
    </script>
</body>

</html>

7.2鼠標事件對象

在這裏插入圖片描述

<!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>
        body {
            height: 3000px;
        }
    </style>
</head>

<body>
    <script>
        //鼠標事件對象MouseEvent
        document.addEventListener('click', function(e) {
            //1.client  鼠標在可視區的x和y座標
            console.log(e.clientX);
            console.log(e.clientY);
            console.log('……………………………………………………');

            //2.page  鼠標在頁面文檔的x和y座標
            console.log(e.pageX);
            console.log(e.pageY);

        })
    </script>
</body>

</html>

圖片跟隨鼠標移動案例:

<!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>
        img {
            position: absolute;
            top: 2px;
        }
    </style>
</head>

<body>
    <img src="angel.gif" alt="">
    <script>
        var pic = document.querySelector('img')
        document.addEventListener('mousemove', function(e) {
            //1.mousemove  只要我們鼠標移動1px  就會觸發這個事件
            // console.log(1);
            var x = e.pageX;
            var y = e.pageY;
            console.log('X座標是' + x, 'Y座標是' + y);
            //不要忘記添加px 單位
            pic.style.left = x - 50 + 'px';
            pic.style.top = y - 40 + 'px';
        });
    </script>
</body>

</html>

八、常用的鍵盤事件

8.1常用鍵盤事件

事件除了使用鼠標觸發,還可以使用鍵盤觸發

在這裏插入圖片描述
注意:

1.如果使用addEventLiatener不需要加on

2.onkeypress 不識別功能鍵 ,比如 左右箭頭 shift等

3.三個事件的執行順序:keydown > keypress >keyup

<!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>
        //1.keyup按鍵彈起的時候觸發
        // document.onkeyup = function() {
        //         console.log('我彈起了');

        //     }
        //2.keydown  按鍵按下的時候觸發
        // document.addEventListener('keydown', function() {
        //         console.log(1111);

        //     })
        //3.keypress 按鍵按下的時候觸發  不能識別功能鍵
        document.addEventListener('keypress', function() {
                console.log(2222);

            })
            //4.三個事件的執行順序  keydown >  keypress  >keyup
    </script>
</body>

</html>

8.2鍵盤事件對象

在這裏插入圖片描述
注意:onkeyup和onkeydown事件不區分字母大小寫,onkeypress區分字母大小寫
在我們實際開發中,我們更多使用keydown和keyup,它能識別所有的鍵(包括功能鍵)
keypress不識別功能鍵,但是keyCode屬性能區分大小寫,返回不同的ASCII值

<!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>
        //鍵盤事件對象中的keycode屬性可以得到相應鍵的ASCII碼值
        //1.我們的keyup和keydown事件不區分字母大小寫 a和A得到的都是65
        //2.我們的keypress事件區分字母大小寫 a  97和 A  65
        document.addEventListener('keyup', function(e) {
            // console.log(e);
            console.log('up:' + e.keyCode);
            //我們可以利用keycode返回的ASCII碼值來判斷用戶按下了哪個鍵
            if (e.keyCode === 65) {
                alert('你按下的a鍵');
            } else {
                alert('你沒有按下a鍵');
            }


        })
        document.addEventListener('keypress', function(e) {
            // console.log(e);
            console.log('press:' + e.keyCode);


        })
    </script>
</body>

</html>

京東按鍵輸入內容:

<!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>
    <input type="text">
    <script>
        var search = document.querySelector('input');
        document.addEventListener('keyup', function(e) {
            // console.log(e.keyCode);
            if (e.keyCode === 83) {
                search.focus();
            }

        })
    </script>
</body>

</html>

模擬京東查詢快遞單號:

<!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>
        .search {
            position: relative;
            width: 178px;
            margin: 100px;
        }
        
        .con {
            display: none;
            position: absolute;
            top: -40px;
            width: 171px;
            border: 1px solid rgb(0, 0, 0, .2);
            box-shadow: 0 2px 4px rgb(0, 0, 0, .2);
            padding: 5px 0;
            font-size: 18px;
            line-height: 20px;
            color: #333;
        }
        
        .con::before {
            content: '';
            width: 0;
            height: 0;
            position: absolute;
            top: 28px;
            left: 18px;
            border: 8px solid #000;
            border-style: solid dashed dashed;
            border-color: #fff transparent transparent;
        }
    </style>
</head>

<body>
    <div class="search">
        <div class="con">123</div>
        <input type="text" placeholder="請輸入你的快遞單號" class="jd">
    </div>
    <script>
        var con = document.querySelector('.con');
        var jd_input = document.querySelector('.jd');
        jd_input.addEventListener('keyup', function() {
            if (this.value == '') {
                con.style.display = 'none';
            } else {
                con.style.display = 'block';
                con.innerHTML = this.value;
            }
            //當我們失去焦點  隱藏con盒子   
            jd_input.addEventListener('blur', function() {
                    con.style.display = 'none';
                })
                //當我們獲得焦點  顯示con盒子   
            jd_input.addEventListener('focus', function() {
                if (this.value != 0) {
                    con.style.display = 'block';
                }
            })
        })
    </script>
</body>

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