事件對象(上)
事件復習
事件三要素: 事件源? + 事件名稱 +? 事件處理程序
事件源 : 誰觸發(fā)這個事件 (按鈕? btn)
事件名稱 : 觸發(fā)了什么事件 (點擊click事件)
事件處理程序 : 事件觸發(fā)后要執(zhí)行的代碼(函數(shù)形式)----可以是有名字的函數(shù)祖搓,要不要加小括號惰帽?不加
事件類型
在事件對象中有個一個屬性type可以獲取到當前事件的類型喻旷。
window.onload=function(e){
varev=e||window.event;
console.log(ev.type);// load
}
鼠標事件
事件? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?描述
click? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?左鍵單擊
contextmenu? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?右鍵單擊
dblclick? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 雙擊
mousedown? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 左鍵按下
mouseup? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 左鍵彈起
mouseover? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?鼠標放上去(在子元素上也會觸發(fā))
mouseout? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?鼠標離開
mouseenter? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 鼠標放上去
mouseleave? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 鼠標離開
mousemove? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 鼠標移動事件
mousewheel? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 鼠標滾輪事件
注意:鼠標滾輪事件有兼容性問題撤缴,在IE、Chrom中是mousewheel,在FireFox中是DOMMouseScroll梅猿,且在FirFox中不能使用on來綁定。在IE和Chrom中向上滾動诵次,事件對象中的wheelDelta是120账蓉,向下滾動是-120,在FirFox中向上滾動逾一,事件對象中的e.detail是3铸本,向下滾動是-3。
案例:星星評分
<body>
<imgsrc="./images/rank_3.gif"alt=""><imgsrc="./images/rank_4.gif"alt="">
<imgsrc="./images/rank_3.gif"alt=""><imgsrc="./images/rank_4.gif"alt="">
<imgsrc="./images/rank_3.gif"alt=""><imgsrc="./images/rank_4.gif"alt="">
<imgsrc="./images/rank_3.gif"alt=""><imgsrc="./images/rank_4.gif"alt="">
<imgsrc="./images/rank_3.gif"alt=""><imgsrc="./images/rank_4.gif"alt="">
</body>
<scripttype="text/javascript">
varimgs=document.querySelectorAll("img");
for(vari=0;i<imgs.length;i++){
imgs[i].index=i;
imgs[i].onmouseover=function(){
for(varj=0;j<=this.index;j++){
if(j%2==0){
imgs[j].src='./images/rank_1.gif'
}else{
imgs[j].src='./images/rank_2.gif'
? ? ? ? ?? }
? ? ?? }
for(varj=this.index+1;j<imgs.length;j++){
if(j%2==0){
imgs[j].src='./images/rank_3.gif'
}else{
imgs[j].src='./images/rank_4.gif'
? ? ? ? ?? }
? ? ?? }
?? }
}
</script>
效果圖:
星星評分效果
瀏覽器事件
事件? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 描述
load? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 加載
unload? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 關(guān)閉
scroll? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 滾動
resize? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?大小改變
鍵盤事件
事件? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?描述
keydown? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 按下
keyup? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?彈起
keypress? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 敲打
鍵盤事件除了用window可以觸發(fā)之外遵堵,還可以使用document箱玷,或者表單元素∧八蓿總之是可以選中的元素锡足。例如div就不行。
表單事件
事件? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?描述
submit? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?提交表單
focus? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?獲取焦點
blur? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?失去焦點
change? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?內(nèi)容改變并失去焦點
input? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?input的value值改變
使用說明:input事件在低版本的IE中不兼容壳坪,使用onpropertychange代替舶得。
事件流
每個事件發(fā)生的時候,都會有一個觸發(fā)并執(zhí)行的過程爽蝴,也就是事件的傳播過程沐批,我們稱之為事件流纫骑。
簡單來說,事件流就是事件從發(fā)生到執(zhí)行結(jié)束的流程九孩。
事件流包含3個階段:捕獲階段先馆、目標階段、冒泡階段
事件捕獲階段:事件開始由頂層元素觸發(fā)躺彬,然后逐級向下傳播煤墙,直到目標元素,依次執(zhí)行其身上綁定的事件顾患。
事件目標階段(處理階段):觸發(fā)當前自身的事件番捂。
事件冒泡階段:事件由目標元素先接收,然后逐級向上傳播江解,達到最頂層元素设预,依次執(zhí)行其身上綁定的事件。
事件流
事件執(zhí)行的流程是先捕獲階段——》再目標元素階段——》最后冒泡階段犁河。
目標元素的事件是在目標階段執(zhí)行鳖枕,其他事件會在冒泡階段執(zhí)行。每個事件只會執(zhí)行一次桨螺,也就是說如果在冒泡階段執(zhí)行了事件宾符,就不會在捕獲階段執(zhí)行。
例:
<body>
<style>
#big{
width:200px;
height:200px;
border:1pxsolid#000;
?? }
#middle{
width:150px;
height:150px;
background:#abcdef;
?? }
#small{
width:100px;
height:100px;
background:red;
?? }
</style>
<divid="big">
?? 大盒子的內(nèi)容
<divid="middle">
? ? ?? 中盒子的內(nèi)容
<divid="small">
? ? ? ? ?? 小盒子的內(nèi)容
</div>
</div>
</div>
</body>
<scripttype="text/javascript">
big.onclick=function(){
console.log(this.innerText);
console.log("大盒子的內(nèi)容完畢");
}
middle.onclick=function(){
console.log(this.innerText);
console.log("中盒子的內(nèi)容完畢");
}
small.onclick=function(){
console.log(this.innerText);
console.log("小盒子的內(nèi)容完畢");
}
</script>
訪問效果:
冒泡示例圖
點擊小盒子灭翔,發(fā)現(xiàn)小盒子事件完畢后魏烫,中盒子的事件也被觸發(fā)了,接著大盒子的事件也被觸發(fā)了肝箱。這就是說目標元素的事件在目標階段執(zhí)行哄褒,其他事件會在冒泡階段執(zhí)行。
<font color="blue">思考:如何讓事件在捕獲階段執(zhí)行煌张?</font>
需要使用另外一種事件綁定方式呐赡。
事件的綁定方式
事件可以綁定在行內(nèi):
<buttononclick="alert(123)">按鈕1</button>
<buttononclick="fn()">按鈕2</button>
<script>
functionfn(){
alert(456)
?? }
</script>
使用on加事件類型綁定事件:
使用on來綁定事件有弊端:同一個事件只能給一個元素綁定一次。
<body>
<buttonid="btn">按鈕</button>
</body>
<script>
btn.onclick=function(){
console.log("第一次單擊");
}
btn.onclick=function(){
console.log("第二次單擊");
}
</script>
訪問效果:
事件覆蓋
解決方案:
使用addEventListener()
語法:
obj.addEventListener(type,handle,false);
# 參數(shù)1:給元素綁定的事件類型骏融,如:click擅编,mouseover妓肢。。。
# 參數(shù)2:處理事件的函數(shù)
# 參數(shù)3:是否在冒泡階段執(zhí)行套媚,true在捕獲階段執(zhí)行碴裙,false在冒泡階段執(zhí)行
例:
<body>
<buttonid="btn">按鈕</button>
</body>
<script>
document.getElementById("btn").addEventListener("click",handle,false);
functionhandle(){
console.log("第一次點擊");
}
document.getElementById("btn").addEventListener("click",handle1,false);
functionhandle1(){
console.log("第二次點擊");
}
</script>
效果:
同一類型事件給元素綁定多次
使用說明:這個方法在IE低版本瀏覽器中不兼容逝段。在IE低版本瀏覽器中使用attachEvent()來代替私股。
語法:
obj.attachEvent('on'+type,handle);
# type表示事件類型
# handle表示處理事件的函數(shù)
使用說明:這種寫法,有個特點:順序注冊事件,執(zhí)行的時候是倒敘執(zhí)行碧囊。
例:
<body>
<buttonid="btn">按鈕</button>
</body>
<script>
document.getElementById("btn").attachEvent("onclick",handle,false);
functionhandle(){
console.log("第一次點擊");
}
document.getElementById("btn").attachEvent("onclick",handle1,false);
functionhandle1(){
console.log("第二次點擊");
}
</script>
運行結(jié)果:
IE中綁定事件執(zhí)行
讓事件在捕獲階段執(zhí)行:
<body>
<style>
#big{
width:200px;
height:200px;
border:1pxsolid#000;
?? }
#middle{
width:150px;
height:150px;
background:#abcdef;
?? }
#small{
width:100px;
height:100px;
background:red;
?? }
</style>
<divid="big">
?? 大盒子的內(nèi)容
<divid="middle">
? ? ?? 中盒子的內(nèi)容
<divid="small">
? ? ? ? ?? 小盒子的內(nèi)容
</div>
</div>
</div>
</body>
<script>
document.getElementById("small").addEventListener("click",Click,true);
document.getElementById("middle").addEventListener("click",Click,true);
document.getElementById("big").addEventListener("click",Click,true);
functionClick(){
console.log(this.innerText);
}
</script>
執(zhí)行效果:
捕獲階段執(zhí)行事件
點擊小盒子的時候树灶,先觸發(fā)大盒子的事件,再觸發(fā)中盒子的事件糯而,最后觸發(fā)小盒子的事件天通。
在IE低版本瀏覽器中的事件沒有捕獲階段,只有冒泡階段熄驼。
通用的綁定和解綁事件
將三種方式的綁定和解綁綜合起來的兼容寫法:
綁定函數(shù)
functionbind(ele,type,callback){
? ? if(ele.addEventListener){
? ? ? ? ele.addEventListener(type,callback,false);
? ? }elseif(ele.detachEvent){
? ? ? ? ele.attachEvent("on"+type,callback);
}else{
ele["on"+type]=callback;
?? }
}
參數(shù)說明:
1. ele:將要綁定事件的對象
2. type:事件類型
3. callback:處理事件的函數(shù)
解綁函數(shù)
functionunbind(ele,type,callback){
? ? if(ele.addEventListener){
? ? ? ? ele.removeEventListener(type,callback,false);
? ? }elseif(ele.detachEvent){
ele.detachEvent("on"+type,callback);
}else{
ele["on"+type]=null;
?? }
}
在實際開發(fā)中像寒,給父元素和子元素綁定事件的場景是很常見的。例:
<font color="blue">思考:如何讓事件不冒泡瓜贾?</font>
需要使用事件對象诺祸。
事件對象
瀏覽器為事件提供了一個對象,用來記錄事件的各種具體信息祭芦,例如筷笨,鼠標點擊的位置、鼠標按鍵的信息龟劲、鍵盤的鍵碼胃夏。。昌跌。
這就是事件對象仰禀。
<body>
<buttonid="btn">按鈕</button>
</body>
<scripttype="text/javascript">
btn.onclick=function(){
console.log(window.event);
}
</script>
點擊訪問結(jié)果:
事件對象
從結(jié)果中可以看出,這個事件對象中包含了事件的類型蚕愤、鼠標點擊的位置答恶,在屏幕中和在瀏覽器中的位置。點開的話萍诱,里面還有很多信息亥宿。
還有另外一種寫法:
btn.onclick=function(e){
console.log(e);
}
以前的時候,前面的寫法是針對IE瀏覽器的砂沛,下面的寫法是針對W3C標準瀏覽器的。上面的寫法曙求,現(xiàn)在基本都兼容了碍庵;下面這種寫法,在IE低版本瀏覽器中還不兼容悟狱。
兼容所有瀏覽器的寫法:
btn.onclick=function(e){
varev=e||window.event
console.log(ev);
}
使用的是短路運算法静浴。
vara=1;
varb;
// 將賦值作為條件,永遠是成立的
if(b=2){
console.log(b);// 2
}
console.log(b);// 2
// 在或者的邏輯中挤渐,如果第一個條件為true苹享,則不再執(zhí)行第二個條件
if(a>0||(b=3)){
console.log(b);// 2
}
console.log(b);// 2
// 只有第一個條件是false的時候才會執(zhí)行第二個條件
if(a>1||(b=3)){
console.log(b);// 2
}
console.log(b);// 2
// 邏輯運算符||兩邊都會轉(zhuǎn)為布爾值進行判斷
// 短路運算
varc=0||1;
console.log(c);// 1
// 因為0轉(zhuǎn)為布爾值是false,所以賦值的時候0沒有執(zhí)行
/* 相當于下面這幾行代碼 */
if(0){
? ? c=0;
}elseif(1){
? ? c=1;
}else{
c=undefined;
}
// 當e是false的時候,將window.event賦值給ev
ev=ev||window.event;
如果是行內(nèi)綁定的事件得问,就將事件對象當做參數(shù)傳進來即可囤攀。<font color="red">且必須是event。</font>
例:
<buttononclcik="fn(event)">
?? 按鈕
</button>
<script>
functionfn(e){
console.log(e);
?? }
</script>
阻止事件冒泡
在事件對象中宫纬,有一個方法用來阻止事件冒泡焚挠,這個方法叫做stopPropagation。
例:
<body>
<style>
#big{
width:200px;
height:200px;
border:1pxsolid#000;
?? }
#middle{
width:150px;
height:150px;
background:#abcdef;
?? }
#small{
width:100px;
height:100px;
background:red;
?? }
</style>
<divid="big">
?? 大盒子的內(nèi)容
<divid="middle">
? ? ?? 中盒子的內(nèi)容
<divid="small">
? ? ? ? ?? 小盒子的內(nèi)容
</div>
</div>
</div>
</body>
<scripttype="text/javascript">
big.onclick=function(){
console.log(this.innerText);
console.log("大盒子的內(nèi)容完畢");
}
middle.onclick=function(){
console.log(this.innerText);
console.log("中盒子的內(nèi)容完畢");
}
small.onclick=function(e){
varev=e||window.event;
ev.stopPropagation();
console.log(this.innerText);
console.log("小盒子的內(nèi)容完畢");
}
</script>
此時漓骚,點擊小盒子蝌衔,不再觸發(fā)父元素的事件。
阻止事件冒泡在IE瀏覽器中有兼容問題蝌蹂,在低版本IE瀏覽器中噩斟,需要使用另外一種寫法:
ev.cancelBubble=true;# IE低版本瀏覽器
例:
small.onclick=function(e){
varev=e||window.event;
ev.cancelBubble=true;
console.log(this.innerText);
console.log("小盒子的內(nèi)容完畢");
}
為了兼容IE低版本瀏覽器,使用兼容寫法:
small.onclick=function(e){
console.log(this.innerText);
console.log("小盒子的內(nèi)容完畢");
varev=e||window.event;
if(ev.stopPropagation){
? ? ev.stopPropagation
}else{
ev.cancelBubble=true;
?? }
}