文章目錄
- 事件概述
-
- 什麼是事件
- 事件對象
- 點選事件的光标坐标的擷取
-
- 相對于你點選的元素
- 相對于浏覽器可視視窗你點選的坐标點
- 相當于頁面你點選的坐标點
- 點選按鍵資訊(了解)
- 常見的事件(了解)
-
- 浏覽器事件
- 滑鼠事件
- 鍵盤事件
- 表單事件
- 觸摸事件
- 鍵盤事件
-
- 确定按鍵
- 常見的鍵盤碼(了解)
- 組合按鍵
- 事件的綁定方式
-
- 事件監聽
- 兩個方式的差別
- 事件的執行機制
-
- 事件的傳播
- 冒泡、捕獲、目标
-
- 目标
- 冒泡
- 捕獲
- 冒泡和捕獲的差別
- 事件委托
-
- 事件觸發
- target
- 委托
- 總結
- 預設行為
-
- 阻止預設行為
事件概述
什麼是事件
- 一個事件由什麼東西組成?
- 觸發誰的事件:事件源
- 觸發什麼事件:事件類型
- 觸發以後做什麼:事件處理函數
var oDiv = document.querySelector('div');
oDiv.onclick = function(){
//誰來觸發事件 => oDiv => 這個事件的事件源就是oDiv
//觸發什麼事件 => onclick => 這個事件類型就是cLick
//觸發之後做什麼 => function(){} => 這個事件的處理函數
}
- 我們想要在點選 div 以後做什麼事情,就把我們要做的事情寫在事件處理函數裡面
var oDiv = document.querySelector('div');
oDiv.onclick = function(){
console.log('你點選了div');
}
- 當我們點選 div 的時候,就會執行時間函數内部的代碼
- 每當點選一次,就會執行一次事件處理函數
事件對象
- 什麼是事件對象?
- 就是當你觸發一個事件以後,對該事件的一些描述資訊
- 例如:
- 你觸發一個點選事件的時候,你點在哪個位置了,坐标是多少
- 你觸發了一個鍵盤事件的時候,你按的是哪個按鈕
- 。。。。。
- 每一個事件都會有一個對應的對象來描述這些資訊,我們就把這個對象叫做事件對象
- 浏覽器給了我們應該黑盒子,叫做
,就是對事件資訊的所有描述window.event
- 比如點選事件
- 你點在了
位置,那麼你得到的這個事件對象裡面對應的就會有一個點位的屬性0,0
- 你點在了
位置,那麼你得到的這個事件對象裡面對應的就會有這個點位的屬性10,10
- 。。。
oDiv.onclick = function(){
console.log(window.event.X軸坐标點資訊);
console.log(window.enent.Y軸坐标點資訊);
}
- 這玩意很好用,但是一般來說,好用的東西就會有相容性問題
- 在
裡面這個東西好用,但是在IE低版本
和高版本IE
裡面不好使了Chrome
- 我們就得用另一種方式來擷取事件對象
- 在每一個事件處理函數的形參位置,預設第一個就是事件對象
oDiv.onclick = function (e){
// e 就是和IE的window.event 一樣的東西
console.log(e.X軸的坐标點資訊);
console.log(e.Y軸坐标點資訊);
}
- 綜上所述,我們以後每一個事件裡面,想要擷取事件對象的時候,都用相容寫法
oDiv.onclick = function(e){
e = e || window.event;
console.log(e.X軸坐标點的資訊);
console.log(e.Y軸坐标點的資訊);
}
點選事件的光标坐标的擷取
- 剛才既然說了,可以擷取到坐标點,那麼接下來我們就學習一下怎麼擷取坐标點
- 我們的每一個點選事件的坐标點都不是一對,因為要有一個相對的坐标系
- 例如:
- 相對事件源(你點選的元素)
- 相對頁面
- 相對浏覽器視窗
- 。。。。。
- 因為都不一樣,是以我們擷取的事件對象裡面的屬性也不一樣
相對于你點選的元素
-
和offsetX
offsetY
- 是相對于你點選的元素的邊框内側開始計算
<style>
* {
margin: 0;
padding: 0;
}
div {
width: 300px;
height: 300px;
padding: 20px;
border: 10px solid #333;
margin: 20px 0 0 30px;
}
</style>
<body>
<div></div>
<script>
var oDiv.document.qerySelector('div');
//注冊點選事件
oDiv.onclick = function(e){
//事件對象相容寫法
e = e || window.event;
console.log(e.offsetX);
console.log(e.offsetY);
}
</script>
</body>
相對于浏覽器可視視窗你點選的坐标點
-
和clientX
clientY
- 是相當于浏覽器視窗來計算的,不管你頁面滾動到什麼情況,都是根據可視視窗來計算坐标
<style>
* {
margin: 0;
padding: 0;
}
body {
width: 2000px;
height: 2000px;
}
div {
width: 300px;
height: 300px;
padding: 20px;
border: 10px solid #333;
margin: 20px 0 0 30px;
}
</style>
<body>
<div></div>
<script>
var oDiv = document.querySelector('div');
//注冊點選事件
oDiv.onclick = function(e){
//事件對象相容寫法
e = e || window.event;
console.log(e.clientX);
console.log(e.clientY);
}
</script>
</body>
相當于頁面你點選的坐标點
-
和pageX
pageY
- 是相對于整個頁面的坐标點,不管有沒有滾動,都是相對于頁面拿到的坐标點
<style>
* {
margin: 0;
padding: 0;
}
body {
width: 2000px;
height: 2000px;
}
div {
width: 300px;
height: 300px;
padding: 20px;
border: 10px solid #333;
margin: 20px 0 0 30px;
}
</style>
<body>
<div></div>
<script>
var oDiv = document.querySelector('div');
//注冊點選事件
oDiv.onclick = function(e){
//事件對象相容寫法
e = e || window.event;
console.log(e.pageX);
console.log(e.pageY);
}
</script>
</body>
點選按鍵資訊(了解)
- 我們的滑鼠一般都有兩個按鍵,一個左鍵一個右鍵
- 我們的事件對象裡面也有一個資訊,确定你點選的是左鍵還是右鍵
- 我們使用
來擷取資訊事件對象.button
- 為滑鼠左鍵,
為滑鼠右鍵2
常見的事件(了解)
- 我們在書寫頁面的時候經常用到的一些事件
- 大緻分為幾類,浏覽器事件、滑鼠事件、鍵盤事件、表單事件、觸摸事件
- 不需要都記住,但是大概要知道
浏覽器事件
-
:頁面全部資源加載完畢load
-
:浏覽器滾動的時候觸發scroll
- 。。。
滑鼠事件
-
:點選事件click
-
:輕按兩下事件dblclick
-
:滑鼠右鍵單擊事件contextmenu
-
:滑鼠左鍵按下事件mousedown
-
:滑鼠左鍵擡起事件mouseup
-
:滑鼠移動事件mousemove
-
:滑鼠移入事件mouseover
-
:滑鼠移出事件mouseout
-
:滑鼠移入事件mouseenter
-
:滑鼠移出事件mouseleave
- 。。。。
鍵盤事件
-
:鍵盤擡起事件keyup
-
:鍵盤按下事件keydown
-
:鍵盤按下再擡起事件keypress
- 。。。。
表單事件
-
:表單内容改變事件change
-
:表單内容輸入事件input
-
:表單送出事件submit
- 。。。。
觸摸事件
-
:觸摸開始事件touchstart
-
:觸摸結束事件touchend
-
:觸摸移動事件touchmove
- 。。。
鍵盤事件
- 剛才了解了一下滑鼠事件,現在來聊聊鍵盤事件
- 我們在鍵盤事件裡面最主要的就是要做兩個事情
- 判斷點選是哪個按鍵
- 有沒有組合按鍵,shift+a/ctrl+b
- 我們先要明确一個問題,就是是不是所有元素都可以綁定鍵盤事件
- 我們說事件有一個關鍵的東西是,該事件是由誰來觸發的
- 一個 div 元素在頁面上,我怎麼能讓一個鍵盤事件觸發在 div 上
- 是以說,我們一般隻給能在頁面上選中的元素(表單元素)和
來綁定鍵盤事件document
oInput.onkeyup =function(){};
document.onkeyup = function(){};
确定按鍵
- 我們的鍵盤上每一個按鍵都有一個自己獨立的編碼
- 我們就是靠這個編碼來确定我們按下的是哪個按鍵的
- 我們通過
或者事件對象.keyCode
來擷取事件對象.which
- 為什麼要有兩個呢,是因為Firefox2.0不支援
是以要使用keycode
which
document.keyup = function(e){
//事件對象的相容寫法
e = e || window.event;
//擷取鍵盤碼的相容寫法
var keyCode = e.keyCode || e.which;
console.log(keyCode);
}
常見的鍵盤碼(了解)
- 8:删除鍵(delete)
- 9:制表符(tab)
- 13:Enter鍵(ebter)
- 16:上檔鍵(shift)
- 17:Ctrl鍵
- 18:alt鍵
- 27:取消鍵(esc)
- 32:空格鍵(space)
- 。。。
組合按鍵
- 組合按鍵最主要的就是
三個按鍵alt、shift、Ctrl
- 在我點選某一個按鍵的時候判斷一下這三個鍵有沒有按下,有就是組合了,沒有就是沒組合
- 事件對象裡面也為我們提供了三個屬性
-
:alt 鍵按下得到true,否則得到falsealtKey
-
:shift 鍵按下得到 true,否則得到 falseshiftKey
-
:ctrl 鍵按下得到 true,否則得到 false;ctrlKey
-
- 我們就可以通過這三個屬性來判斷是否按下了
document.onkeyup = function(e){
e = e || window.event;
keyCode = e.keyCode || e.which;
if(e.altKey && keyCode === 65){
console.log("你同時按下了 alt 和 a");
}
}
事件的綁定方式
- 我們現在給一個注冊事件都是使用
的方式onxxx
- 但是這個方式不是很好,隻能給一個元素注冊一個事件
- 一旦寫了第二個事件,那麼第一個就被覆寫了
oDiv.onclick = function(){
console.log('我是第一個事件');
}
oDiv.onclick = function(){
console.log('我是第二個事件');
}
- 當你點選的時候,隻會執行第二個,第一個就沒有了
- 我們還有一種事件監聽的方式給元素綁定事件
- 使用
的方式添加addEventListener
- 這個方法不相容,在IE裡面要使用
attachEvent
- 這個方法不相容,在IE裡面要使用
事件監聽
-
:非IE 7、8使用addEventListener
- 文法:
元素.addEventListener('事件類型',事件處理函數,冒泡還是補貨);
oDiv.addEventListener('click',function(){
console.log('我是第一個事件');
},false)
oDiv.addEventListenner('click',function(){
console.log('我是第二個事件');
},false)
- 當你點選 div 的時候,兩個函數都會執行,标簽會按照你注冊的順序執行
- 先列印`我是第一個事件`再列印`我是第二個事件`
- 注意:事件的類型不要寫on,點選事件就是click,不是onclick
-
:IE 7 8下使用attchEvent
- 文法:
元素.attachEvent('事件類型',事件處理函數);
oDiv.attachEvent('onclick',function(){
console.log("我是第一個事件");
})
oDiv.attackEvent('onclick',function(){
console.log('我是第二個事件');
})
- 當你點選div 的時候,兩個函數都會執行,并且會按照你注冊的順序倒叙執行
- 先列印 我是第二個事件 再列印 我是第一個事件
- 注意:事件類型要寫on,點選事件就寫onclick
兩個方式的差別
- 注冊事件的時候事件類型參數的書寫
-
:不用寫onaddEventListener
-
:要寫onattachEvent
-
- 參數個數
-
:一般是3個常用參數addEventListener
-
:2個參數attachEvent
-
- 執行順序
-
:順序注冊,順序執行addEventListener
-
:順序注冊,倒叙執行attachEvent
-
- 适用浏覽器
-
:非IE 7 8的浏覽器addEventListener
-
:IE 7 8浏覽器attachEvent
-
事件的執行機制
- 什麼是事件的執行機制呢?
- 思考一個問題:
- 當一個大盒子嵌套一個小盒子的時候,并且兩個盒子都有點選事件
- 你點選裡面的小盒子,外面的大盒子上的點選事件要不要執行
事件的傳播
- 就像上面那個圖檔一樣,我們點選在紅色盒子身上的同時,也是點選在了粉色盒子上
- 這個是既定事實,那麼兩個盒子的點選事件都會觸發
- 這個就叫做 事件的傳播
- 當元素觸發一個事件的時候,其父元素也會觸發相同的事件,父元素的父元素也會觸發相同的事件
- 就像上面的圖檔一樣
- 點選在紅色盒子上的時候,會觸發紅色盒子的點選事件
- 也是點選在了粉色的盒子上,也會觸發粉色盒子的點選事件
- 也是點選在了 body 上,也會觸發 body 的點選事件
- 也是點選在了 html 上,也會觸發 html 的點選事件
- 也是點選在了 document 上,也會觸發 document 的點選事件
- 也是點選在了 window 上,也會觸發 window 的點選事件
- 也就是說,頁面上任何一個元素觸發事件,都會一層一層最終導緻 window 的相同僚件觸發,前提是各層級元素得有注冊相同的事件,不然不會觸發
- 在事件傳播的過程中,有一些注意的點:
- 隻會傳播同類事件
- 隻會從點選元素開始按照 html 的結構逐層向上元素的事件會被觸發
- 内部元素不管有沒有該事件,隻要上層元素有該事件,那麼上層元素的事件就會被觸發
- 到現在,我們已經了解了事件的傳播,我們再來思考一個問題
- 事件确實會從自己開始,到 window 的所有相同僚件都會觸發
- 是因為我們點在自己身上,也确實逐層的點在了直至 window 的每一個元素身上
- 但是到底是先點在自己身上,還是先點在了 window 身上呢
-
先點在自己身上,就是先執行自己的事件處理函數,逐層向上最後執行 window 的事件處理函數
反之,則是先執行 window 的事件處理函數,逐層向下最後執行自己身上的事件處理函數
冒泡、捕獲、目标
- 我們剛才聊過了,每一個事件,都是有可能從自己到 window ,有可能要執行多個同類型事件
- 那麼這個執行的順序就有一些說法了
目标
- 你是點選在哪個元素身上了,那麼這個事件的 目标 就是什麼
冒泡
- 就是從事件 目标 的事件處理函數開始,依次向外,直到 window 的事件處理函數觸發
- 也就是從下向上的執行事件處理函數
捕獲
- 就是從 window 的事件處理函數開始,依次向内,隻要事件 目标 的事件處理函數執行
- 也就是從上向下的執行事件處理函數
冒泡和捕獲的差別
- 就是在事件的傳播中,多個同類型事件處理函數的執行順序不同
事件委托
- 就是把我要做的事情委托給别人來做
- 因為我們的冒泡機制,點選子元素的時候,也會同步觸發父元素的相同僚件
- 是以我們就可以把子元素的事件委托給父元素來做
事件觸發
- 點選子元素的時候,不管子元素有沒有點選事件,隻要父元素有點選事件,那麼就可以出發父元素的點選事件
<body>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
<script>
var oUl = document.querySelector('ul');
oUL.addEventListener('click',function(e){
console.log('我是 ul 的點選事件,我被觸發了');
})
</script>
</body>
- 像上面一段代碼,當你點選 ul 的時候肯定會觸發
- 但是當你點選 li 的時候,其實也會觸發
target
- target 這個屬性是事件對象裡面的屬性,表示你點選的目标
- 當你觸發點選事件的時候,你點選在哪個元素上,target 就是哪個元素
- 這個 target 也不相容,在 IE 下要使用 srcElement
<body>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
<script>
var oUl = docuemnt.querySelector('ul')
oUl.addEventListener('click', function (e) {
e = e || window.event
var target = e.target || e.srcElement
console.log(target)
})
</script>
</body>
- 上面的代碼,當你點選 ul 的時候,target 就是 ul
- 當你點選在 li 上面的時候,target 就是 li
委托
- 這個時候,當我們點選 li 的時候,也可以觸發 ul 的點事件
- 這個時候,當我們點選 li 的時候,也可以觸發 ul 的點事件
- 這個時候,我們就可以把 li 的事件委托給 ul 來做
<body>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
<script>
var oUl = docuemnt.querySelector('ul')
oUl.addEventListener('click', function (e) {
e = e || window.event
var target = e.target || e.srcElement
// 判斷你點選的是 li
if (target.nodeName.toUpperCase === 'LI') {
// 确定點選的是 li
// 因為當你點選在 ul 上面的時候,nodeName 應該是 'UL'
// 去做點選 li 的時候該做的事情了
console.log('我是 li,我被點選了')
}
})
</script>
</body>
- 上面的代碼,我們就可以把 li 要做的事情委托給 ul 來做
總結
- 為什麼要用事件委托
- 我頁面上本身沒有 li
- 我通過代碼添加了一些 li
- 添加進來的 li 是沒有點選事件的
- 我每次動态的操作完 li 以後都要從新給 li 綁定一次點選事件
- 比較麻煩
- 這個時候隻要委托給 ul 就可以了
- 因為新加進來的 li 也是 ul 的子元素,點選的時候也可以觸發 ul 的點選事件
- 事件委托的書寫
- 元素的事件隻能委托給結構父級或者再結構父級的同樣的事件上
- li 的點選事件,就不能委托給 ul 的滑鼠移入事件
- li 的點選事件,隻能委托給 ul 或者在高父級的點選事件上
預設行為
- 預設行為,就是不用我們注冊,它自己就存在的事情
- 比如我們點選滑鼠右鍵的時候,會自動彈出一個菜單
- 比如我們點選 a 标簽的時候,我們不需要注冊點選事件,他自己就會跳轉頁面
- 。。。
- 這些不需要我們注冊就能實作的事情,我們叫做 預設事件
阻止預設行為
- 有的時候,我們不希望浏覽器執行預設事件
- 比如我給 a 标簽綁定了一個點選事件,我點選你的時候希望你能告訴我你的位址是什麼
- 而不是直接跳轉連結
- 那麼我們就要把 a 标簽原先的預設事件阻止,不讓他執行預設事件
- 我們有兩個方法來阻止預設事件
-
: 非 IE 使用e.preventDefault()
-
:IE 使用e.returnValue = false
-
- 我們阻止預設事件的時候也要寫一個相容的寫法
<a href="https://www.baidu.com">點選我試試</a>
<script>
var oA = document.querySelector('a')
a.addEventListener('click', function (e) {
e = e || window.event
console.log(this.href)
e.preventDefault ? e.preventDefault() : e.returnValue = false
})
</script>
- 這樣寫完以後,你點選 a 标簽的時候,就不會跳轉連結了
- 而是會在控制台列印出 a 标簽的 href 屬性的值