事件处理程序

简介

js和html之间的交互是通过事件实现的,所谓事件就是文档或浏览器窗口中发生的一些特定的交互瞬间。对于事件的处理,浏览器存在差异,主要是IE的兼容性问题,所以大部分都是兼容的,封装成一个事件库,方便调用。


1、事件流

事件流描述的是从页面接收事件的顺序,分为事件冒泡流和事件捕获流

事件冒泡:IE浏览器的事件流,开始由最具体的元素接收,然后逐级向上传播到不那么具体的节点上

事件捕获:Netscape提出的,开始由不那么具体的节点,然后逐级向下传播到最具体的元素接收;在事件到达之前捕获它(老浏览器不支持,建议用事件冒泡)

DOM事件流:DOM2规定事件流包括事件捕获,处于目标阶段和事件冒泡

2、事件处理程序

响应某个事件的函数就是事件处理程序

2.1HTML事件处理程序

<div class="div" title="div box" onclick="changeColor()" onmouseover="alert(this.title)"></div>
function changeColor(){
alert("变颜色")
}
这种就为html事件处理程序
优点:拓展作用域,可以无需引用元素就可以访问元素属性
缺点:时差问题,事件函数不一致,一般onclick="try{showMessage()}catch(ex){}";html和js过于耦合,一般不采取
给相应的属性值设置为null,也可以删除了事件处理程序

2.2DOM0级事件处理程序

<div id="div" title="div box"></div>
div=document.getELementById("div")
div.onclick=function(){
alert("DOM0级事件处理程序")
alert(this.title) 事件处理程序就是在元素的作用域下进行的,可以用this
}
div.onclick=null 删除事件处理程序(通用)

2.3DOM2级事件处理程序

DOM定义事件处理程序有两种方法:

addEventListener(),removeEventListener(),接受三个参数,处理的事件名、事件函数、布尔值(true为捕获,false为冒泡,默认为false)

var div=document.getElementById("div")
div.addEventListener("click",function(){alert("DOM2级事件处理程序")},false)
div.addEventListener("click",function(){alert("可以添加几个事件处理程序,顺序执行")},false)
当removeEventListener时候,中间事件函数必须为函数表达式,不能为匿名函数
div.addEventListener("click",handler,false)
var handler=function(){
alert("函数表达式形式")
}
div.removeEventListener("click",handler,false) 这里可以删除事件处理程序

补充

 addEventListener的第三个参数

1 默认为false即冒泡事件,在都不添加的情况下为冒泡

2 一旦有设置为true的,则true先触发

3 在没有子节点的时候,即单一触发,则谁先谁触发

<label>Click me <input type="text"></label>
<script>
    document.querySelector('label').addEventListener('click',function () {
        console.log(1)
    })
    document.querySelector('input').addEventListener('click',function () {
        console.log(2)
    })
</script>

了解label和input间的绑定关系即可知道,每点击label的时候,也会点击input,那么在这种情况下,会弹出1 2 1    第一则为label自己,而2 1 则是冒泡事件 

2.4IE事件处理程序

与DOM2级相似为attachEvent()和detachEven(),接受两个参数,处理事件名(这里是带on的),事件函数

var div=document.getELementById("div")
div.attachEvent("onclick",function(){alert("IE浏览器")}) 这里的和DOM0级的区别在于作用域,DOM0级为该元素内,而IE为整个window,this为window,后面的event对象为window.event
div.attachEvent("onclick",function(){alert("多个事件则以相反顺序执行")})
detachEvent和DOM2级一样的

2.5跨浏览器兼容

var EventUtil={
//添加事件处理程序 addHandler:
function(element,type,handler){ //handler为函数,需要函数表达式,不会函数提升的 if(element.addEventListener){ element.addEventListener(type,handler,false); } else if(element.attachEvent){ element.attachEvent("on"+type,handler); } else{ element["on"+type]=handler; } }, //删除事件处理程序 removeHandler:function(element,type,handler){ if(element.removeEventListener){ element.removeEventListener(type,handler,false) } else if(element.detachEvent){ element.detachEvent("on"+type,handler) } else{ element["on"+type]=null } } }

3、事件对象

当触发DOM事件时,就会产生一个事件对象event,包含着所有与事件有关的信息,包括导致事件的元素、事件的类型、以及其他与特定事件相关的信息,浏览器支持event,但方式不一,event对象常见的属性和方法

DOM中

type为事件类型

target为事件目标

currentTarget正在处理事件的元素,即谁在处理事件程序就是谁,为this,而target则是总是在实际触发事件的元素上的。

preventDefault()取消事件默认行为,比如a标签本身的跳转

stopPropagation()取消事件的进一步捕获或冒泡

IE中

type为事件类型

srcElement为事件目标

returnValue设置为false取消事件默认行为

cancelBubble设置为true取消事件冒泡

直接上兼容版的

var EventUtil={              
             //兼容event对象(关键)
             getEvent:function(event){
                  return event?event:window.event;
             },
             //获得目标
             getTarget:function(event){
                  return event.target||event.srcElement;
             },
             //取消默认行为
             previousDefault:function(event){
                 if(event.previousDefault){
                     event.previousDefault();
                 }
                 else{
                     event.returnValue=false;
                 }
             },
             //取消事件冒泡
             stopPropagation:function(event){
                  if(event.stopPropagation){
                      event.stopPropagation();
                  }
                  else{
                      event.cancelBubble=true;
                  }
             },
       }

 4事件类型

4.1UI事件

load事件

当页面完全加载后在window触发;当img加载后在img上触发;一般用js指定事件处理程序,当然在html内body也可以的,

EventUtil.addHandler(window,"load",function(){
                   var  image=document.createElement("img")
                   document.body.appendChild(image)
                   image.src="console.png"
                   EventUtil.addHandler(image,"load",function(event){
                            event=EventUtil.getEvent(event)
                            alert(EventUtil.getTarget(event).src)          //在图像完全加载后获得信息
                   })
          })

unload事件

当页面完全卸载后触发,从一个页面跳转到另一个页面就会触发unload事件,一般利用其清楚引用,以免避免内存泄露。

resize事件

当改变窗口大小就会触发,以1px为单位

scroll事件

当页面滚动时发生,单位因各个浏览器不同,scrollTop和scrollLeft的兼容性问题

4.2焦点事件

焦点事件会在页面元素获得失去焦点时触发,与document.hasFocus(),document.activeElement属性配合,知道用户在页面的行踪

blur失去焦点时触发,不会冒泡

focus获得焦点时触发,不会冒泡

focusout失去焦点时触发,会冒泡

focusin获得焦点时触发,会冒泡

4.3鼠标事件

客户区坐标位置

EventUtil.addHandler(window,"load",function(event){
                   EventUtil.addHandler(window,"click",function(event){
                            event=EventUtil.getEvent(event)
                            alert(event.clientX+","+event.clientY)
                   })
          })
总是相对于整个可视区范围的

页面坐标位置

EventUtil.addHandler(window,"click",function(event){
                    event=EventUtil.getEvent(event)
                    console.log(event.pageX+","+event.pageY)
          })
两个效果一样的,page事实上为scrollTop和clientY的和,下面这种兼容性可以的
EventUtil.addHandler(window,"click",function(event){
                   var event=EventUtil.getEvent(event)
                   var scrollTop=Math.ceil(document.documentElement.scrollTop||document.body.scrollTop)
                   alert(event.clientX+","+(event.clientY+scrollTop))
          })

修改键

键盘上的某些键也可以达到鼠标键的效果,DOM中常见的有shiftKey,ctryKey,altKey,metaKey(window or cmd),都是布尔值。

EventUtil.addHandler(another,"click",function(event){
                 event=EventUtil.getEvent(event)
                 var key=[]
                 if(event.ctrlKey){
                      key.push("ctrlKey")
                 }
                 if(event.shiftKey){
                      key.push("shiftKey")
                 }
                 if(event.altKey){
                      key.push("altKey")
                 }
                 if(event.metaKey){
                     key.push("metaKey")
                 }
                console.log(key.join(","))
       })

屏幕坐标位置

EventUtil.addHandler(window,"click",function(event){
                    event=EventUtil.getEvent(event)
                    console.log(event.screenX+","+event.screenY)
          })

相关元素

一般对于mouseover和mouseout,其他的事件为null,当从原来的元素转移到另一元素,另一元素即为相关元素

getRelatedTarget:function(event){
                 if(event.relatedTarget){
                      return event.relatedTarget;
                 }
                  else if(event.toElement){       兼容IE8版本
                       return event.toElement
                  }
                  else if(event.formElement){
                       return event.formElement
                  }
                else{
                    return null
                }
             },

鼠标按钮

 getButton:function(event){
                   if(document.implementation.hasFeature("MouseEvent","2.0")){
                          return event.button
                   }
                   else{
                        switch(event.button){
                             case 0:
                             case 1:
                             case 3:
                             case 5:
                             case 7:
                                return 0;
                             case 2:
                             case 6:
                                return 2;
                             case 4:
                                return 1;
                        }
                   }
             },

鼠标滚轮事件

触发mousewheel事件(火狐为DOMMouseScroll),event对象属性wheelDelta,可以得到滚轮的增量值,IE为正负120,Chrome为正负150,火狐为正负120

             //鼠标滚轮事件mousewheel
             getWheelDelta:function(event){
                  if(event.wheelDelta){
                       return (client.engine.opear&&client.engine.opear<9.5?-event.wheelDelta:event.wheelDelta);
                  }
                  else{
                       return -event.detail*40;
                  }
             },

var client=function(){     //声明浏览器引擎问题
                 var engine={
                      //呈现引擎
                      ie:0,
                      gecko:0,
                      webkit:0,
                      khtml:0,
                      opera:0,
                      //具体版本号
                      ver:null
                 };
                 return{
                       engine:engine
                 };
          }();

(function(){ //这里的函数是个私有作用域,不会让其干预到全局作用域 function handlerMouseWheel(event){ event=EventUtil.getEvent(event); var delta=EventUtil.getWheelDelta(event) console.log(delta); } EventUtil.addHandler(window,"mousewheel",handlerMouseWheel); //其他浏览器 EventUtil.addHandler(window,"DOMMouseScroll",handlerMouseWheel); //火狐浏览器 })()

4.4键盘和文本事件

键盘事件主要有三个keydown任意键,keypress字符键,keyup释放键,这三个在输入文本时常用;文本事件为textInput,在文本输入文本框中才触发。

键码:发生键盘事件时,event对象中keyCode属性进行判断,keyCode属性值和ASCII相对应,

常用的keyCode为

空格键32 tab键9 enter键13  shift键16  Ctrl键17 alt键18 backspace键8 方向键37,38,39,40

字符编码:按下能够插入或删除字符的键才触发charCode属性,只有发生keypress时才包含,表示其的ASCII编码,

              //字符编码
             getCharCode:function(event){
                 if(typeof event.charCode=="number"){
                      return event.charCode;
                 }
                 else{
                      return event.keyCode; 
                 }
             },

            EventUtil.addHandler(text1,"keypress",function(event){
                 event=EventUtil.getEvent(event)
               console.log(EventUtil.getCharCode(event))
            })

 4.5HTML5事件

contextmenu事件

单击右键触发上下文事件,将原来的默认事件取消,contextmenu事件是冒泡的,所以用可以用document处理页面所有此类事件

#move{
   width:200px;
   height:400px;
   background:pink;
   position:absolute;
   display:none;
}

  var move=document.getElementById("move")
EventUtil.addHandler(document,"contextmenu",function(event){ event=EventUtil.getEvent(event) EventUtil.previousDefault(event) move.style.left=event.clientX+"px" move.style.top=event.clientY+"px" move.style.display="block" EventUtil.addHandler(document,"click",function(event){ move.style.display="none" }) })

beforeunload事件

当页面卸载前阻止这一操作(比如刷新),将控制权交给用户,是否卸载此页面,提醒作用

    EventUtil.addHandler(window,"beforeunload",function(event){
                     event=EventUtil.getEvent(event)
                     EventUtil.previousDefault(event)
                     var message="really to leave"                   
          })

DOMContentLoaded事件

此事件在load事件之前发生,不会因为加载外部的css或者js等文件资源而延迟,使得用户更早的交互,对于不支持此事件比如IE8,9等,可以采用定时器的方法

          setTimeout(function(){alert("breforeload"),0})  对于不支持的采取这种,但是也不可以保证
EventUtil.addHandler(window,
"load",function(){ alert("load") }) EventUtil.addHandler(document,"DOMContentLoaded",function(event){ alert("beforeload") })

readystatechange事件:提供与文档或元素加载状况的信息

pageshow和pagehide事件

往返缓存(bfcache),可以在用户使用浏览器后退或前进按钮加载页面的转换速度,不仅保存页面数据,还保存DOM,js状态,将整个页面保存在内存中。

pageshow事件。在页面显示时触发,无论是否来自bfcache,虽然是在document触发的,但是必须在window上进行事件程序员处理

function change(){
                  var count=0

                  EventUtil.addHandler(window,"load",function(){
                       alert("load")
                  })

                  EventUtil.addHandler(window,"pageshow",function(event){
                         count++
                         alert(event.persisted)   //判断页面是否保存在往返缓存中,布尔值
                  })

                  EventUtil.addHandler(window,"pagehide",function(event){
                         alert(event.persisted)   //当卸载页面时触发
                  })
          }
 change()

hashchange事件

在URL的参数列表发生变化时通知,在Ajax应用中,利用URL参数列表保存状态或导航信息;此时Event有oldURL和newURL属性分别保存前后完整的参数列表的URL,不过兼容浏览器直接用location判断。

EventUtil.addHandler(window,"hashchange",function(event){
                      alert(locationn.hash)     //使用location对象确定当前的参数列表
          })

4.6设备事件暂时不考虑,等涉及到移动端再好好补充

5内存和性能

5.1事件委托

所谓事件委托就是利用事件冒泡,只给指定一个事件处理程序,就可以管理某一类型的所有事件,解决的就是事件处理程序太多的问题,以此提高性能;适合采用这种方法的有click,mousedown,keydown,keyup,keypress

EventUtil.addHandler(list,"click",function(event){      只需要在一个ul上添加事件,然后通过target来实现行为,这也就是target和currentTarget之间的区别,好处多多
                    event=EventUtil.getEvent(event)
                    var target=EventUtil.getTarget(event)

                    switch(target.id){                //利用条件判断
                           case "baidu":
                                target.style.color="red"
                                target.style.cursor="pointer"
                                document.title="i have change"
                                break;
                           case "ali":
                                location.href="http://www.baidu.com"
                                break;
                           case "tengxun":
                                alert("Tencent")
                                break;
                    }
          })

5.2移除事件程序

当不需要事件时,需要将已有的事件处理程序移除即那些过时不用的空事件处理程序(dangling event handler),比如innerHTML代替原来的东西,原来的事件必须移除以此提高性能。当已知的元素即将移除,最好手工移除事件比如下面。

var btn=document.getElementById("btn")
          btn.onclick=function(){
                  alert("事件发生后,我就不再需要了")
                  btn.onclick=null
          }

模拟事件暂时不需要,以后再细细道来

基础不牢,地动山摇

posted @ 2018-01-19 18:15  决起而飞  阅读(385)  评论(0编辑  收藏  举报