dom事件
- 1.什么是事件?
事件就是一件事情或者行為(對(duì)于元素來說他的很多事件都是天生自帶)只要我們?nèi)ゲ僮鬟@個(gè)元素就會(huì)觸發(fā)事件。
事件就是元素天生自帶的行為,我們操作元素就會(huì)觸發(fā)相關(guān)的事件行為
- 2.事件綁定:給元素天生自帶的事件行為綁定方法,當(dāng)事件觸發(fā)會(huì)把對(duì)應(yīng)的方法執(zhí)行
- 3.元素天生自帶的事件
鼠標(biāo)事件
click
:點(diǎn)擊(pc端是點(diǎn)擊惨奕,移動(dòng)端的click代表單擊,并且使用click會(huì)有300ms的延遲)
dblclick
:雙擊
mouseover
:鼠標(biāo)經(jīng)過
mouseout
:鼠標(biāo)移出
mouseenter
:鼠標(biāo)進(jìn)入
mouseleave
:鼠標(biāo)離開
mousemove
:鼠標(biāo)移動(dòng)
mousedown
:鼠標(biāo)按下(鼠標(biāo)左右鍵都起作用他是按下即觸發(fā)竭钝,click是按下抬起才出發(fā)梨撞,而且是先把down和up先觸發(fā)雹洗,click才觸發(fā))
mouseup
:鼠標(biāo)抬起
mousewheel
:鼠標(biāo)滾輪滾動(dòng)
鍵盤事件
keydown
:鍵盤按下
keyup
:鍵盤抬起
keypress
:和keydown類似只不過keydown返回的是鍵盤碼。keypress返回的是ASCII碼值
[圖片上傳失敗...(image-51ec19-1570785135646)]
input
:由于pc有實(shí)體物理鍵盤聋袋,可以監(jiān)聽到鍵盤的按下和抬起,但是移動(dòng)端
是虛擬的鍵盤穴吹,所以keydown和keyup在大部分手機(jī)上都沒有幽勒,我們使用input事件統(tǒng)一代替他們(內(nèi)容改變事件)
表單元素常用的事件
focus
:獲取焦點(diǎn)
blur
:失去焦點(diǎn)
change
:內(nèi)容改變
其他常用事件
load
:加載完成
unload
:
beforeunload
:
scroll
:滾動(dòng)條滾動(dòng)事件
resize
:大小改變事件window.onresize=function(){}當(dāng)瀏覽器窗口大小發(fā)生改變會(huì)觸發(fā)這個(gè)事件執(zhí)行對(duì)應(yīng)的事情。
readystatechange
:ajax狀態(tài)改變
移動(dòng)端手指事件
gesture
:多指操作
touchstart
:手指按下
touchmove
:手指移動(dòng)
touchend
:手指離開
touchcancel
:因?yàn)橐馔馇闆r導(dǎo)致手指操作取消
gesturestart
:多指按下
gesturechange
:多指改變
gestureend
:手指離開
h5中的audio港令、video音頻事件
canplay
啥容;可以播放(播放過程中可能出現(xiàn)由于資源沒有加載完成導(dǎo)致卡頓
canplaythrough
:資源加載完成可以正常無障礙播放
事件綁定
DOM0級(jí)事件綁定
[element].onxxx=function(){};
DOM2級(jí)事件綁定
[element].addEventListener('xxx',function(){},false);
[element].attachEvent('onxxx',function(){});[ie6-8];
給元素的事件行為綁定方法,當(dāng)行為觸發(fā)的時(shí)候?yàn)g覽器會(huì)把綁定的方法執(zhí)行
1.方法中的this:當(dāng)前操作的元素(除非自己改動(dòng)this顷霹,比如箭頭函數(shù)咪惠,或者bind)
2.事件綁定屬于異步操作,綁定的時(shí)候方法沒有執(zhí)行淋淀,還是創(chuàng)建方法的階段呢遥昧,當(dāng)行為觸發(fā)瀏覽器才會(huì)把方法執(zhí)行。(當(dāng)然也有變態(tài)的執(zhí)行方式:bo.onclick(),這樣執(zhí)行僅僅是把它當(dāng)做一個(gè)變量和函數(shù)執(zhí)行朵纷,和事件沒啥關(guān)系炭臭。)
3.瀏覽器不僅把這個(gè)方法執(zhí)行了,還記錄了當(dāng)前本次操作的相關(guān)信息(如果是鼠標(biāo)點(diǎn)擊袍辞,瀏覽器記錄點(diǎn)擊的位置鞋仍,點(diǎn)的是誰(shuí)等信息),把這些信息都存儲(chǔ)到一個(gè)對(duì)象中(這個(gè)對(duì)象就是實(shí)踐對(duì)象:記錄當(dāng)前本次操作信息的對(duì)象)搅吁;更重要的是標(biāo)準(zhǔn)瀏覽器會(huì)把這個(gè)對(duì)象(堆內(nèi)存)傳遞給執(zhí)行的方法威创。我們可以在方法中通過形參或者實(shí)參集合等方式受到傳遞的事件對(duì)象信息;
目的:給當(dāng)前元素的某個(gè)事件綁定方法不管是基于dom0還是dom2都是為了觸發(fā)元素的相關(guān)行為的時(shí)候能做點(diǎn)事情也就是把綁定的方法執(zhí)行谎懦;不僅把方法執(zhí)行了而且瀏覽器還給方法傳遞了一個(gè)實(shí)參信息值===》這個(gè)值就是
事件對(duì)象ev
目的:事件對(duì)象中記錄了很多屬性名和屬性值肚豺,這些信息中包含了當(dāng)前操作的基礎(chǔ)信息,例如鼠標(biāo)點(diǎn)擊位置的x/y軸坐標(biāo)界拦,鼠標(biāo)點(diǎn)擊的是誰(shuí)(事件源)等信息
box.onclick=function(ev){//定義一個(gè)形參ev用來接收方法執(zhí)行的時(shí)候详炬,瀏覽器傳遞的信息值(事件對(duì)象mouseevent鼠標(biāo)事件對(duì)象,keyboardevent鍵盤事件對(duì)象寞奸,event普通事件對(duì)象呛谜。。)
//目的:事件對(duì)象中記錄了很多屬性名和屬性值枪萄,這些信息中包含了當(dāng)前操作的基礎(chǔ)信息隐岛,例如鼠標(biāo)點(diǎn)擊位置的x/y軸坐標(biāo),鼠標(biāo)點(diǎn)擊的是誰(shuí)(事件源)等信息
console.log(ev);}
ev.target
:事件源(操作的是哪個(gè)元素)ev.srcElement;
低版本瀏覽器
ev.clientX/ev.clientY
:當(dāng)前鼠標(biāo)觸發(fā)點(diǎn)距離當(dāng)前窗口左上角的x/y軸坐標(biāo)
ev.pageX/ev.pageY
:當(dāng)前鼠標(biāo)觸發(fā)點(diǎn)距離body(第一屏)左上角的x/y軸坐標(biāo)瓷翻。
ev.preventDefault()
:阻止默認(rèn)行為
ev.stopPropagation()
:阻止事件的冒泡傳播
ev.cancelBubble = true;
//=>低版本阻止冒泡傳播
ev.type
:當(dāng)前事件類型
[圖片上傳失敗...(image-12f843-1570785135646)]
[用到其中的幾個(gè)屬性聚凹,需要處理兼容]
box割坠。onclick=function(ev){
ev=ev||window.event;
let target=ev.target||ev.srcElement,
pageY=ev.pageY||(ev.clientY+(document.documentElement.scrollTop||document.body.scrollTop))};
[很多地方都用到這些屬性,而且用的多]
function handleEvent(ev){
if(window.event&&!ev){//低版本瀏覽器妒牙,我們需要處理的不僅僅是把ev賦值彼哼,還要把高版本中有低版本沒有的屬性給ev加上
ev=window.event;
ev.target=ev.srcElement;
ev.pageX=ev.clientX+(document.documentElement.scrollLeft||document.body.scrollLeft;
ev.pageY=ev.clientY+(document.documentElement.scrollTop||document.body.scrollTop;
ev.which=ev.keyCode;
ev.preventDefault=function(){
ev.return=false;
}
ev.stopPropagation=function(){
ev.cancelBubble=true
}
}
return ev;
}
box.onclick=function(ev){
ev.handleEvent(ev);
let target=ev.target;
}
keyboardEvent
ev.code:當(dāng)前按鍵“keyE”
ev.key:當(dāng)前按鍵'e'
ev.which/ev.keycode:當(dāng)前按鍵的鍵盤碼69
常用的鍵盤碼
左 - 上 - 右 - 下
:37-38-39-40
Backspace刪除鍵
:18
Enter
:13
Space
:32
Delete
:46
Shift
:16
Alt
:18
Ctrl
:17
Esc
:27
F1-F12
:112-123
0-9
:48-57
a-z
:小寫字母
[圖片上傳失敗...(image-347bfa-1570785135646)]
box.onclick = function(ev){
if(!ev){
//兼容思想:低版本沒有的屬性,我們手動(dòng)設(shè)置一些:按照自己有的先獲取到值湘今,然后賦值給標(biāo)準(zhǔn)對(duì)應(yīng)的新屬性(經(jīng)過判斷處理后敢朱,低版本中也有target/pageX/pageY這些屬性),后期在使用的時(shí)候摩瞎,直接按照高版本的使用即可
ev = window.event;
console.log(ev.srcElement); //=>ev.srcElement是獲取事件源(標(biāo)準(zhǔn)瀏覽器使用的是ev.target)
console.log(ev.ev.pageX); //=>低版本瀏覽器的事件對(duì)象中不存在pageX/pageY
ev.target = ev.srcElement拴签;
ev.pageX = ev.clientX+(document.documentElement.scrollLeft||document.body.scrollLeft)
ev.pageY = ev.clientX+(document.documentElement.scrollTop||document.body.scrollTop)
ev.which = ev.keyCode;
//ev.preventDefault ev.stopPropagation 低版本不存在
ev.preventDefault = function(){
ev.returnValue = false; //低版本阻止默認(rèn)行為
}
ev.stopPropagation = function(){
ev.cancelBubble= true; //低版本阻止冒泡傳播
}
}
//=>直接按照高版本的規(guī)則使用
console.log(ev.target,ev.which);
}
//兼容處理方法二
box.onclick = function(){
//用到誰(shuí),給誰(shuí)處理兼容
ev=ev || window.event;
var target = ev.target || ev.srcElement;
ev.preventDefault()?ev.preventDefault()():ev.returnValue=false;
}
事件的默認(rèn)行為
事件本身就是天生就有的旗们,某些事件觸發(fā)即使你沒有綁定方法也會(huì)存在一些效果蚓哩,這些默認(rèn)的效果就是
事件的默認(rèn)行為
1.點(diǎn)擊A實(shí)現(xiàn)頁(yè)面跳轉(zhuǎn)
2.錨點(diǎn)定位(href=“元素的ID”),點(diǎn)擊的時(shí)候url中設(shè)置對(duì)應(yīng)的hash值(#xxx)上渴,頁(yè)面加載完成后會(huì)定位到ID和hash值相同的盒子位置岸梨。真實(shí)項(xiàng)目中就是一個(gè)普通按鈕,不想實(shí)現(xiàn)頁(yè)面跳轉(zhuǎn)或者錨點(diǎn)定位稠氮。此時(shí)我們需要阻止點(diǎn)擊A的時(shí)候的默認(rèn)行為盛嘿。
結(jié)構(gòu)上阻止:href="JavaScript:;"
或者void(0),null;undefined;
js方法阻止:
link.onclick=function(ev){
ev=ev||window.event;
ev.preventDefault?ev.preventDefault():ev.returnValue=false;
}
或者link.onclick=function(){
return false;
//原理:點(diǎn)擊A的時(shí)候首先觸發(fā)的是click其次才會(huì)觸發(fā)它的默認(rèn)行為,我們?cè)赾lick中返回false其意思是阻止下一步繼續(xù)操作括袒。
}
基于hash值可以實(shí)現(xiàn)spa單頁(yè)面應(yīng)用
input標(biāo)簽也有自己的默認(rèn)行為
1.輸入內(nèi)容可以呈現(xiàn)到文本框中
2.輸入內(nèi)容的時(shí)候會(huì)把之前輸入的一些信息呈現(xiàn)出來次兆,并不是所有瀏覽器和所有情況下都有
//真實(shí)項(xiàng)目中我們根據(jù)需求可能會(huì)組織文本框輸入內(nèi)容,此時(shí)其實(shí)就是阻止他的默認(rèn)行為
userInp.onkeydown=userInp.onkeyup=function(ev){
let val=this.value.trim(),
len=val.length;
if(len>10){
this.value=val.substr(0,10);超過十位的截掉
有值的鍵是不允許輸入的del/back-space/space/shift/ctrl/alt/tab...
}
}
submit按鈕也存在默認(rèn)行為
1.點(diǎn)擊按鈕頁(yè)面會(huì)刷新
<from action='wangzhi'><input type='submit'></from>
事件的傳播機(jī)制
冒泡傳播:觸發(fā)當(dāng)前元素的某一個(gè)事件(點(diǎn)擊事件)行為不僅當(dāng)前元素事件行為觸發(fā)锹锰,而且其祖先元素的相關(guān)事件行為也會(huì)一次被觸發(fā)芥炭,這種機(jī)制就是
事件的冒泡傳播機(jī)制
。
- 捕獲階段:點(diǎn)擊inner的時(shí)候首先會(huì)從最外層開始向內(nèi)查找的(找到操作的事件源)恃慧,查找的目的是構(gòu)建出冒泡傳播階段需要傳播的路線(查找就是按照HTML層級(jí)結(jié)構(gòu)找的)
- 目標(biāo)階段:把事件源的相關(guān)操作行為觸發(fā)(如果綁定了方法則把方法執(zhí)行)
- 冒泡傳播:按照捕獲階段規(guī)劃的路線自內(nèi)而外把當(dāng)前事件源的祖先元素的相關(guān)事件行為一次觸發(fā)(如果某一個(gè)祖先元素事件行為綁定了方法园蝠,則把方法執(zhí)行,沒綁定方法痢士,行為觸發(fā)了彪薛,什么都不做,繼續(xù)向上傳播即可)
[圖片上傳失敗...(image-a72b79-1570785135646)]
xxx.onxxx=function(){};dom0事件綁定怠蹂,給元素的事件行為綁定方法這些都是在當(dāng)前元素事件行為的冒泡階段或者目標(biāo)階段執(zhí)行的
xxx.addEventListener('xxx',function(){},false)第三個(gè)參數(shù)false也是控制綁定的方法在事件傳播的冒泡階段或者目標(biāo)階段執(zhí)行善延,只有第三個(gè)參數(shù)為true才代表讓當(dāng)前方法在事件傳播的冒泡階段或者目標(biāo)階段執(zhí)行
不同瀏覽器對(duì)最外層祖先元素的定義是不一樣的
谷歌:window->document->html->body...
IE高:window->html->body...
IE低:html->body...
關(guān)于事件對(duì)象的一些理解
1.事件對(duì)象是用來存儲(chǔ)當(dāng)前本次操作的相關(guān)信息,和操作有關(guān)城侧,和元素?zé)o必然關(guān)聯(lián)易遣,
2.當(dāng)我們基于鼠標(biāo)或者鍵盤等操作的時(shí)候,瀏覽器會(huì)把本次操作的信息存儲(chǔ)起來(標(biāo)準(zhǔn)瀏覽器存儲(chǔ)到默認(rèn)的內(nèi)存中(自己找不到)嫌佑,IE低版本存儲(chǔ)到window.event中了)存儲(chǔ)的值是一個(gè)對(duì)象(堆內(nèi)存);操作肯定會(huì)觸發(fā)元素的某個(gè)行為豆茫,綁定的方法侨歉,執(zhí)行此時(shí)標(biāo)準(zhǔn)瀏覽器會(huì)把之前存儲(chǔ)的對(duì)象(準(zhǔn)確來說是堆內(nèi)存地址)當(dāng)做實(shí)參傳遞給每一個(gè)執(zhí)行方法,所以操作一次即使更多方法中都有ev揩魂,但是存儲(chǔ)的值都是一個(gè)(本次操作信息的對(duì)象而已)
mouseenter和mouseover區(qū)別
over屬于滑過覆蓋事件幽邓,從父元素進(jìn)入到子元素屬于離開了父元素,會(huì)觸發(fā)父元素的out觸發(fā)子元素的over
enter屬于進(jìn)入火脉,從父元素進(jìn)入子元素牵舵,并不算離開父元素,不會(huì)觸發(fā)父元素的leave觸發(fā)子元素的enter忘分。
enter和leave阻止了事件的冒泡傳播棋枕,而over和out還存在冒泡傳播白修。
所以對(duì)于父元素嵌套子元素這種情況使用over會(huì)發(fā)生很多不愿意操作的事情妒峦,此時(shí)我們使用enter會(huì)更簡(jiǎn)單,操作方便兵睛,所以真實(shí)項(xiàng)目中用enter的使用會(huì)比over多肯骇。
[圖片上傳失敗...(image-82f92c-1570785135646)]
事件委托
利用事件的冒泡傳播機(jī)制,如果一個(gè)容器的后代元素中很多元素的點(diǎn)擊行為都要做一些處理此時(shí)我們不需要像以前一樣一個(gè)一個(gè)獲取然后綁定了祖很,我們只需要給容器的click綁定方法即可笛丙,這樣不管點(diǎn)擊是哪個(gè)后代元素,都會(huì)根據(jù)冒泡傳播的傳遞機(jī)制假颇,把容器的click行為觸發(fā)胚鸯,把對(duì)應(yīng)的方法執(zhí)行,根據(jù)事件源我們可以知道點(diǎn)擊的是誰(shuí)從而做不同的事情
初步了解JS中事件綁定的方式
DOM0事件綁定
oBox.onclick=function(e){
//=>this:oBox
e=e||window.event;
}
oBox.onmouseenter=function(){}
...
DOM2事件綁定
//=>標(biāo)準(zhǔn)瀏覽器
oBox.addEventListener('click',function(e){
//=>this:oBox
//=>e:事件對(duì)象
},false);
//=>false:讓當(dāng)前綁定的方法在冒泡傳播階段執(zhí)行(一般都用FALSE)
//=>true:讓當(dāng)前綁定的方法在捕獲階段執(zhí)行(一般不用)
//=>IE6~8
oBox.attachEvent('onclick',function(e){
//=>e:事件對(duì)象笨鸡,不同于DOM0事件綁定姜钳,使用attachEvent綁定方法,當(dāng)事件觸發(fā)方法執(zhí)行的時(shí)候形耗,瀏覽器也會(huì)把事件對(duì)象當(dāng)做實(shí)參傳遞給函數(shù)(傳遞的值和window.event是相同的)哥桥,所以IE6~8下獲取的事件對(duì)象對(duì)于:pageX\pageY\target...依然沒有,還是存在兼容性(事件對(duì)象兼容處理在DOM2中依然存在)
});
//=>此時(shí)綁定的方法都是在冒泡傳播階段執(zhí)行
有DOM0和DOM2事件綁定激涤,那么DOM1事件綁定呢拟糕?
因?yàn)樵贒OM第一代升級(jí)迭代的時(shí)候,DOM元素的事件綁定方式依然沿用的是DOM0代綁定的方式倦踢,在此版本DOM中送滞,事件綁定沒有升級(jí)處理
DOM0事件綁定和DOM2事件綁定的區(qū)別
DOM0事件綁定的原理
1、給當(dāng)前元素對(duì)象的某一個(gè)私有屬性(onxxx這樣的私有屬性)賦值的過程(之前屬性默認(rèn)值是null辱挥,如果我們給賦值一個(gè)函數(shù)累澡,相當(dāng)于綁定了一個(gè)方法)
2、當(dāng)我們賦值成功(賦值一個(gè)函數(shù))般贼,此時(shí)瀏覽器會(huì)把DOM元素和賦值的函數(shù)建立關(guān)聯(lián)愧哟,以及建立DOM元素行為操作的監(jiān)聽奥吩,當(dāng)某一個(gè)行為被用戶觸發(fā),瀏覽器會(huì)把相關(guān)行為賦值的函數(shù)執(zhí)行特點(diǎn):
//=>1蕊梧、只有DOM元素天生擁有這個(gè)私有屬性(onxxx事件私有屬性)霞赫,我們賦值的方法才叫做事件綁定,否則屬于給當(dāng)前元素設(shè)置一個(gè)自定義屬性而已
document.body.onclick=function(){}//->事件綁定
/*
* 手動(dòng)點(diǎn)擊頁(yè)面中的BODY觸發(fā)方法執(zhí)行
* document.body.onclick() 這樣執(zhí)行也可以
*/
document.body.onzhufeng=function(){}//->設(shè)置自定義屬性
/*
* 只能document.body.onzhufeng()這樣執(zhí)行
*/
//=>2肥矢、移除事件綁定的時(shí)候端衰,我們只需要賦值為null即可
document.body.onclick=null;
//=>3、在DOM0事件綁定中甘改,只能給當(dāng)前元素的某一個(gè)事件行為(某一個(gè)事件私有屬性)綁定一個(gè)方法旅东,綁定多個(gè)方法,最后一次綁定的會(huì)把之前綁定的都替換掉
document.body.onclick=function(){
console.log(1);
}
document.body.onclick=function(){
console.log(2);
}
//=>點(diǎn)擊BODY只能輸出2十艾,因?yàn)榈诙钨x值的函數(shù)把第一次賦值的函數(shù)給替換了
DOM2事件綁定的原理
1抵代、我們DOM2事件綁定使用的addEventListener/attachEvent都是在EventTarget這個(gè)內(nèi)置類的原型上定義的,我們調(diào)取使用的時(shí)候忘嫉,首先通過原型鏈找到這個(gè)方法荤牍,然后執(zhí)行完成事件綁定的效果2、瀏覽器首先會(huì)給當(dāng)前元素的某一個(gè)事件行為開辟一個(gè)事件池(事件隊(duì)列)[其實(shí)是瀏覽器有一個(gè)統(tǒng)一的事件池庆冕,我們每個(gè)元素的某個(gè)行為綁定的方法都放在這個(gè)事件池中康吵,只是通過相關(guān)的標(biāo)識(shí)來區(qū)分的],當(dāng)我們通過addEventListener做事件監(jiān)聽的時(shí)候访递,會(huì)把綁定的方法存放在事件池中
3晦嵌、當(dāng)元素的某一個(gè)行為觸發(fā),瀏覽器會(huì)到對(duì)應(yīng)的事件池中拷姿,把當(dāng)前存放在事件池中的所有方法惭载,依次按照存放的先后順序執(zhí)行
特點(diǎn):
//=>1、所有DOM0支持的事件行為跌前,DOM2都可以使用棕兼,不僅如此,DOM2還支持一些DOM0沒有的事件行為:DOMContentLoaded...
window.onDOMContentLoaded === undefined; //=>DOM0中沒有這個(gè)屬性
window.addEventListener('DOMContentLoaded',function(){
//=>標(biāo)準(zhǔn)瀏覽器中兼容這個(gè)事件:當(dāng)瀏覽器中的DOM結(jié)構(gòu)加載完成抵乓,就會(huì)觸發(fā)這個(gè)事件(也會(huì)把綁定的方法執(zhí)行)
},false);
window.attachEvent('onDOMContentLoaded',function(){
//=>IE6~8中的DOM2也不支持這個(gè)事件
});
//=>2伴挚、DOM2中可以給當(dāng)前元素的某一個(gè)事件行為綁定‘多個(gè)不同的方法’(因?yàn)榻壎ǖ乃蟹椒ǘ即娣旁谑录刂辛耍?function fn1(){
console.log(1);
}
function fn2(){
console.log(2);
}
function fn3(){
console.log(3);
}
document.body.addEventListener('click',fn1,false);
document.body.addEventListener('click',fn3,false);
document.body.addEventListener('click',fn2,false);
document.body.addEventListener('click',fn3,false);//=>本次向事件池中存儲(chǔ)的時(shí)候,發(fā)現(xiàn)fn3已經(jīng)在事件池中存在了灾炭,不能再存儲(chǔ)了
//3茎芋、DOM2事件綁定的移除比較麻煩一些,需要和綁定的時(shí)候:事件類型蜈出、綁定的方法田弥、傳播階段,三個(gè)完全一致才可以移除掉
document.body.removeEventListener('click',fn2,false);
document.body.addEventListener('click',function(){
console.log(1);
},false);
document.body.removeEventListener('click',function(){
console.log(1);
},false);
//=>DOM2事件綁定需要我們養(yǎng)成‘未雨綢繆’的能力铡原,綁定方法的時(shí)候盡量不用匿名函數(shù)偷厦,為后期可能會(huì)把方法在事件池中移除掉做準(zhǔn)備
dom0:
box.onclick=function(){};每一個(gè)元素對(duì)象都是對(duì)應(yīng)類的實(shí)例商叹,瀏覽器天生為其設(shè)置了很多私有屬性和公有的屬性方法,而onclick就是其中的一個(gè)私有屬性(事件類私有屬性只泼,還有很多其他的事件私有屬性剖笙,)
這些屬性值默認(rèn)為null
dom0事件綁定的原理:就是給元素的某一個(gè)事件私有屬性賦值(瀏覽器會(huì)建立監(jiān)聽機(jī)會(huì),當(dāng)我們觸發(fā)元素的某個(gè)行為请唱,瀏覽器會(huì)把屬性中賦的值去執(zhí)行)
dom0事件綁定弥咪,只允許給當(dāng)前元素的某個(gè)事件行為綁定一個(gè)方法,多次綁定后面綁定的會(huì)替換前面綁定的十绑,以最后一次綁定的方法為主
dom2:
box.addEventListener('click',function(){},false)還有removeEventListener('click',function(){},false)移除聚至,(使用的方法都是EventTarget.prototype定義的),完成時(shí)間幫頂是基于事件池機(jī)制完成的本橙。
在IE低版本當(dāng)中使用的是attachEvent來處理的扳躬,box.attachEvent('onclick',function(){})移除使用的是dettachEvent
dom2事件綁定可以給當(dāng)前元素的某一個(gè)事件行為綁定“多個(gè)不同的方法”。
dom2事件綁定的兼容
谷歌vsie高版本
在一處事件綁定的時(shí)候如果移除操作發(fā)生在正要執(zhí)行的方法之前勋功,如點(diǎn)擊的時(shí)候坦报,正要執(zhí)行F8但是在執(zhí)行Fn4的時(shí)候沃恩吧fn8從是堅(jiān)持中移除了库说,谷歌下是立即移除生效狂鞋,第一次也不再執(zhí)行FN8了而IE是當(dāng)前本次不生效,下一次點(diǎn)擊才生效潜的,第一次點(diǎn)擊還是要執(zhí)行FN8的
標(biāo)準(zhǔn)vsIE低版本
標(biāo)準(zhǔn):addEventListener/removeEventListener
Ie低版本:attchEvent/dettachEvent
1.this問題:標(biāo)準(zhǔn)瀏覽器中行為觸發(fā)方法執(zhí)行方法中的this是當(dāng)前元素本身骚揍,IE低版本中this執(zhí)行了window
2.重復(fù)問題:標(biāo)準(zhǔn)瀏覽器中的是堅(jiān)持是默認(rèn)去重復(fù)的,同一個(gè)元素的同一個(gè)事件行為不能出現(xiàn)相同的綁定方法啰挪,但是IE低版本的事件池機(jī)制沒有那么完善信不,不能默認(rèn)去重,也就是可以給同個(gè)元素的同個(gè)事件綁定相同的方法了
3.順序問題:標(biāo)準(zhǔn)瀏覽器是按照向事件池中存放的順序依次執(zhí)行的亡呵,而IE低版本是亂序執(zhí)行的沒有規(guī)律
IE低版本瀏覽器出現(xiàn)的所有問題都是由于本身自帶的事件池機(jī)制不完善導(dǎo)致的
dom0和dom2事件綁定的區(qū)別
:
1.機(jī)制不同:
dom0采用給私有屬性賦值抽活,所以只能綁定一個(gè)方法
dom2采用的是事件池機(jī)制,能綁定多個(gè)不同的方法
2.移除的操作不同:
box.onclick=function(){};
box.onclick=null;賦值為null就移除了
box.addEventListener('click',function(){console.log(1)},false);
box.removeEventListener('click',function(){console.log(1)},false);
dom2在移除的時(shí)候必須清楚要移除哪一個(gè)方法才能在事件池中移除掉所以基于dom2做事件綁定锰什,我們要有瞻前顧后的思路下硕,也就是綁定的時(shí)候考慮一下如何移除(技巧不要綁定匿名函數(shù),都綁定實(shí)名函數(shù))
3.dom2事件綁定中增加了一些domo無法操作的事件行為汁胆,例如DOMContentLoaded事件(當(dāng)頁(yè)面中的HTML結(jié)構(gòu)加載完成就會(huì)觸發(fā)執(zhí)行)
JQ中的事件綁定
on / off:基于DOM2事件綁定實(shí)現(xiàn)事件的綁定和移除(兼容了所有的瀏覽器)
one:只綁定一次梭姓,第一次執(zhí)行完成后,會(huì)把綁定的方法移除(基于ON/OFF完成的)
click / mouseover / mouseout ...:JQ提供快捷綁定方法嫩码,但是這些方法最后都是基于ON/OFF完成的
delegate:事件委托方法(1.7版本以前用的是live方法)
bind / unbind:正常綁定
window.onload和$(document).ready()
window.onload = function () {
//=>當(dāng)頁(yè)面中的資源都加載完成(HTML結(jié)構(gòu)加載完誉尖、CSS和JS等資源加載完成等)才會(huì)觸發(fā)執(zhí)行
};
// window.addEventListener('load',function(){}); //=>這樣處理也可以執(zhí)行多次了
//=>$(document).ready(function(){})
//原理:基于DOMContentLoaded完成的(IE中用的是onreadystatechange監(jiān)聽的,在document.readyState === "complete"時(shí)候執(zhí)行函數(shù))
$(function () {
//=>當(dāng)頁(yè)面中的HTML結(jié)構(gòu)加載完成就會(huì)執(zhí)行
});
$(function(){
//=>基于DOM2事件綁定的铸题,所以在同一個(gè)頁(yè)面中可以執(zhí)行多次(綁定多個(gè)不同的方法)铡恕,當(dāng)結(jié)構(gòu)加載完成琢感,會(huì)依次執(zhí)行這些方法
});
window.onload和$(document).ready()的區(qū)別
window.onload:當(dāng)瀏覽器中所有的資源內(nèi)容(DOM結(jié)構(gòu)、文本內(nèi)容探熔、圖片...)都加載完成猩谊,觸發(fā)load事件
1、它是基于DOM0事件綁定完成的祭刚,所以在同一個(gè)頁(yè)面中只能給它綁定一個(gè)方法(綁定多個(gè)也以最后一個(gè)綁定的為主)2牌捷、如果想在一個(gè)頁(yè)面中使用多次,我們應(yīng)該是基于DOM2事件綁定的
function fn1(){
//=>第一件事情
}
function fn2(){
//=>第二件事情
}
window.addEventListener('load',fn1,false);
window.addEventListener('load',fn2,false);
...
$(function(){}) 或者 $(document).ready(function(){})
當(dāng)文檔中的DOM結(jié)構(gòu)加載完成就會(huì)被觸發(fā)執(zhí)行涡驮,而且在同一個(gè)頁(yè)面中可以使用多次1暗甥、JQ中提供的方法,JQ是基于DOMContentLoaded這個(gè)事件完成這個(gè)操作的
2捉捅、JQ中的事件綁定都是基于DOM2事件綁定完成的
3撤防、但是DOMContentLoaded在IE68下使用attachEvent也是不支持的,JQ在IE68中使用的是readystatechange這個(gè)事件處理的
DOM2事件綁定的兼容處理
語(yǔ)法上的兼容處理
[標(biāo)準(zhǔn)]
curEle.addEventListener('type',fn,false);
[IE6~8]
curEle.attachEvent('ontype',fn);
//=>ON:給當(dāng)前元素的某個(gè)事件綁定某個(gè)方法
var on = function (curEle, type, fn) {
if (document.addEventListener) {
//=>標(biāo)準(zhǔn)瀏覽器
curEle.addEventListener(type, fn, false);
return;
}
//=>IE6~8
curEle.attachEvent('on' + type, fn);
};
//=>OFF:移除當(dāng)前元素某個(gè)事件綁定的某個(gè)方法
var off = function (curEle, type, fn) {
if (document.removeEventListener) {
curEle.removeEventListener(type, fn, false);
return;
}
//=>IE6~8
curEle.detachEvent('on' + type, fn);
};
除了語(yǔ)法上的區(qū)別棒口,在處理的機(jī)制上有一些區(qū)別
在IE6~8中使用attachEvent做事件綁定(把方法存放在當(dāng)前元素指定事件類型的事件池中)
1寄月、順序問題:當(dāng)事件行為觸發(fā),執(zhí)行對(duì)應(yīng)事件池中存放方法的時(shí)候无牵,IE低版本瀏覽器執(zhí)行方法的順序是亂序(標(biāo)準(zhǔn)瀏覽器是按照綁定的先后順序依次執(zhí)行的)
2漾肮、重復(fù)問題:IE低版本瀏覽器在向事件池中增加方法的時(shí)候,沒有去重機(jī)制茎毁,哪怕當(dāng)前方法已經(jīng)存放過了克懊,還會(huì)重復(fù)的添加進(jìn)去(標(biāo)準(zhǔn)瀏覽器的事件池機(jī)制很完善,可以自動(dòng)去重:已經(jīng)存在過的方法不允許在添加進(jìn)來)
3七蜘、THIS問題:IE低版本瀏覽器中谭溉,當(dāng)事件行為觸發(fā),把事件池中方法執(zhí)行橡卤,此時(shí)方法中的this指向window扮念,而不是像標(biāo)準(zhǔn)瀏覽器一樣,指向當(dāng)前元素本身
究其根本:其實(shí)都是IE低版本瀏覽器對(duì)于它內(nèi)置事件池處理機(jī)制的不完善導(dǎo)致的
DOM2事件綁定兼容處理的原理:告別LOW的IE68的內(nèi)置事件池碧库,而是自己創(chuàng)建一個(gè)類似于標(biāo)準(zhǔn)瀏覽器的“自定義事件池”柜与,標(biāo)準(zhǔn)瀏覽器不需要處理兼容,只有IE68中才需要處理兼容