事件处理程序

简介

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


一、事件流

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

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

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

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

二、事件处理程序

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

2.1HTML事件处理程序app

<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级事件处理程序ide

<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 } } }

三、事件对象

当触发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
          }

模拟事件暂时不须要,之后再细细道来

基础不牢,地动山摇

相关文章
相关标签/搜索