一靴迫、事件流
1举塔、冒泡
- 什么是事件冒泡
官方的定義就是從最特定的事件目標(biāo)到最不特定的事件目標(biāo)冤议。
意思就是說(shuō),假如用戶單擊了一個(gè)元素,該元素?fù)碛幸粋€(gè)click事件,那么同樣的事件也將會(huì)被它的祖先觸發(fā),這個(gè)事件從該元素開(kāi)始一直冒泡到DOM樹(shù)的最上層,這一過(guò)程稱為事件冒泡
示例:
html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>自定義右鍵菜單</title>
</head>
<body>
<ul id='menu'>
<li>menu item 1</li>
<li>menu item 2</li>
</ul>
</body>
</html>
js
document.oncontextmenu =function (){
alert('觸發(fā)了);
}
2侦高、捕獲
- 什么是事件捕獲
事件捕獲和事件是相反的,也就是說(shuō),當(dāng)用戶觸發(fā)了一個(gè)事件的時(shí)候,這個(gè)事件是從DOM樹(shù)的最上層開(kāi)始觸發(fā)一直到捕獲到事件源.
標(biāo)準(zhǔn)的監(jiān)聽(tīng)事件方式(標(biāo)準(zhǔn)瀏覽器都可使用械馆,IE9以上)
element.addEventListener(eventType, fn, false)
說(shuō)明:
- 第一個(gè)參數(shù): eventType:事件類型
- 第二個(gè)參數(shù):fn 觸發(fā)的回調(diào)函數(shù)
- 第三個(gè)參數(shù):一個(gè)布爾值胖眷,表示冒泡還是捕獲。false表示冒泡,true表示捕獲
IE下的監(jiān)聽(tīng)事件方式(IE專有)
·attachEvent(eventType,fn)· IE專有霹崎。
說(shuō)明:
此種監(jiān)聽(tīng)方式只有冒泡沒(méi)有捕獲珊搀。
注意:
- 標(biāo)準(zhǔn)監(jiān)聽(tīng)方式不需加on
document.addEventlistener('contextmenu',function (){
alert('我是標(biāo)準(zhǔn)的我不需要on')
},false)
- IE監(jiān)聽(tīng)事件方式必須加on
document.attachEvent('oncontextmenu',function(){
alert('我是IE的我需要on')
})
一般使用標(biāo)準(zhǔn)即可,如果兼容IE 8以下再考慮第二種尾菇,做兼容方式的書寫食棕。
二、oncontextmenu
屬于鼠標(biāo)事件错沽,鼠標(biāo)右鍵點(diǎn)擊即觸發(fā)簿晓。
用法:
我在document
上綁定了此事件,通過(guò)事件冒泡機(jī)制觸發(fā)千埃。
document.oncontextmenu =function (){
alert('觸發(fā)了);
}
3憔儿、事件對(duì)象event
概念:
Event 對(duì)象代表事件的狀態(tài),比如事件在其中發(fā)生的元素放可、鍵盤按鍵的狀態(tài)谒臼、鼠標(biāo)的位置、鼠標(biāo)按鈕的狀態(tài)耀里。
事件通常與函數(shù)結(jié)合使用蜈缤,函數(shù)不會(huì)在事件發(fā)生前被執(zhí)行
- 標(biāo)準(zhǔn)瀏覽器中作為事件回調(diào)函數(shù)的第一個(gè)參數(shù)
document.addEventlistener('contextmenu',function(ev){
alert(ev)
})
- 低版本的IE作為window對(duì)象的一個(gè)屬性
document.attachEvent('onc ontextmenu',function(){
alert(window.event)
})
一般如果不兼容ie 8以下,用標(biāo)準(zhǔn)下的event即可
4冯挎、取消默認(rèn)行為
event.preventDefault()
5底哥、阻止冒泡
event.stopPropagation()
說(shuō)明:
return false
既可以阻止默認(rèn)行為,也可以阻止冒泡
6、獲取滾動(dòng)距離
- chrome:
document.body.scrollTop(scrollLeft)
- 非chrome:
document.documentElement.scrollTop(scrollLeft)
- 兼容寫法:
var scrollTop = document.documentElement.scrollTop||document.body.scrollTop,
var scrollLeft = document.documentElement.scrollLeft||document.body.scrollLeft,
7趾徽、clientX(Y)
它提供事件發(fā)生時(shí)的應(yīng)用客戶端區(qū)域的水平坐標(biāo) (與頁(yè)面坐標(biāo)不同)续滋。例如,當(dāng)你點(diǎn)擊客戶端區(qū)域的左上角時(shí)孵奶,鼠標(biāo)事件的 clientX 值為 0 疲酌,這一值與頁(yè)面是否有水平滾動(dòng)無(wú)關(guān)
也就是說(shuō)到瀏覽器可視窗口的距離(不包括瀏覽器的工具欄)
8、 獲取元素具體尺寸
offsetHeight/offsetWidth
通常了袁,元素的offsetHeight是一種衡量標(biāo)準(zhǔn)朗恳,包括元素的邊框、垂直(水平)內(nèi)邊距和元素的水平(垂直)滾動(dòng)條(如果存在且渲染的話)和元素的CSS高度(寬度)
注意:
與clientWidth/clientHeight
的區(qū)別是载绿,`clientWidth/clientHeight 不包括邊框僻肖,和垂直(水平)滾動(dòng)條的寬度(高度)
9、獲取瀏覽器視口的尺寸
var browserHeight = document.documentElement.clientHeight,//瀏覽器視口的高度
browserWidth = document.documentElement.clientWidth;
注意:
一開(kāi)始使用了window.innerWidth/window.innerHeight
來(lái)獲取視口尺寸卢鹦,結(jié)果在極限情況下被滾動(dòng)條覆蓋一部分臀脏,后來(lái)找到原因是:window.innerWidth/window.innerHeight
是把滾動(dòng)條也算在內(nèi)的
10、類數(shù)組轉(zhuǎn)換成數(shù)組
Array.prototype.slice.call(類數(shù)組,0)
11冀自、自定義右鍵菜單實(shí)現(xiàn)思路
1揉稚、讓自定義菜單相對(duì)于瀏覽器視口做絕對(duì)定位通過(guò)改變left/top
值來(lái)改變每次菜單的位置
2、取消原來(lái)的右鍵菜單默認(rèn)行為
3熬粗、考慮極限情況搀玖,判斷event.clientX+菜單的offsetWidth/event.clientY+offsetHeight
是否大于等于 document.documentElement.clientWidth/document.documemtElement.clientHeight
,如果大于等于,則把left/top
賦值為event.clientX-菜單的offsetWidth/event.clientY-菜單的offsetHeight
,否則賦值為event.clientX/event.clientY
js代碼:
window.onload = function (){
var oClick = document.getElementById('click_region'),
oMenu = document.getElementById('menu'),
aLi = oMenu.getElementsByTagName('li'),
browserHeight = document.documentElement.clientHeight,//瀏覽器視口的高度
browserWidth = document.documentElement.clientWidth; //瀏覽器視口的快讀驻呐,不包括垂直滾動(dòng)天的寬度
document.oncontextmenu = function (ev){
oMenu.style.display = 'block';
var ev = ev||window.event,
scrollTop = document.documentElement.scrollTop||document.body.scrollTop,
scrollLeft = document.documentElement.scrollLeft||document.body.scrollLeft,
clientX = ev.clientX,
clientY = ev.clientY,
// 注意:只有在隱藏的元素變成display:block的狀態(tài)才能獲取他的寬度和高度
offsetWidth = oMenu.offsetWidth,
offsetHeight = oMenu.offsetHeight,
top,
left;
if(clientY+offsetHeight>=browserHeight){
top = clientY-offsetHeight
}else{
top = clientY
}
if(clientX+offsetWidth>=browserWidth){
left = clientX-offsetWidth
console.log(left);
}else{
left = clientX
}
oMenu.style.left = left+'px';
oMenu.style.top =scrollTop+top+'px';
return false//阻止默認(rèn)行為灌诅,并且阻止冒泡
}
// 取消自定義菜單
document.onclick = function (){
oMenu.style.display = 'none';
}
var lis = Array.prototype.slice.call(aLi,0); //類數(shù)組轉(zhuǎn)成數(shù)組
//遍歷數(shù)組
lis.forEach(function (item,index,arr){
aLi[index].onclick = function (event){
alert(this.innerHTML)
event.stopPropagation();
}
})
}