事件处理程序

摘要:
简介js和html之间的交互是通过事件实现的。所谓的事件是发生在文档或浏览器窗口中的一些特定交互时刻。对于事件处理,浏览器是不同的,主要是因为IE的兼容性,所以大多数浏览器都是兼容的,并封装到事件库中,以便调用。PreventDefault()取消默认事件行为。例如,标记a本身的跳转stopPropagation()取消了事件的进一步捕获或冒泡。在IE中,类型是事件类型,srcElement是事件目标,returnValue设置为false,取消事件默认行为,cancelBubble设置为true,取消事件冒泡。直接兼容版本varEventUtil={//兼容事件对象(键)getEvent:函数{returnevent?

简介

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


1、事件流

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

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

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

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

2、事件处理程序

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

2.1HTML事件处理程序

<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   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){
                      returnevent.relatedTarget;
                 }
                  else if(event.toElement){       兼容IE8版本
                       returnevent.toElement
                  }
                  else if(event.formElement){
                       returnevent.formElement
                  }
                else{
                    return null}
             },

鼠标按钮

 getButton:function(event){
                   if(document.implementation.hasFeature("MouseEvent","2.0")){
                          returnevent.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(){ //这里的函数是个私有作用域,不会让其干预到全局作用域 functionhandlerMouseWheel(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"){
                      returnevent.charCode;
                 }
                 else{
                      returnevent.keyCode; 
                 }
             },

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

4.5HTML5事件

contextmenu事件

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

#move{
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上进行事件程序员处理

functionchange(){
                  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}

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

基础不牢,地动山摇

免责声明:文章转载自《事件处理程序》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇DOM,javascript,Web API之间的关系——onclick 引起的思考与调研迅雷/快车/旋风地址转换器下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Corona SDK新手教程:tap、touch和multitouch的区别

本教程主要讲解一下tap、touch和multitouch的区别,以及如何处理每种方式。 如果是新手的话,可以先复习一下之前的文章 CoronaSDK之交互系统和事件检测 1 Tap检测 Tap事件是用户和触屏之间交互最基础的一种。本质上来说,一个tap就是表示用户用手指接触到屏幕,然后在差不多附近的位置再抬起的过程。这个tap事件只有在用户在同一个点接触...

libevent源码学习(8):event_signal_map解析

目录event_signal_map结构体向event_signal_map中添加event激活event_signal_map中的event删除event_signal_map中的event以下源码均基于libevent-2.0.21-stable。       在前文中分析了event_io_map,在windows环境下event_io_map定义为...

LMAX Disruptor—多生产者多消费者中,消息复制分发的高性能实现

解决的问题 当我们有多个消息的生产者线程,一个消费者线程时,他们之间如何进行高并发、线程安全的协调? 很简单,用一个队列。 当我们有多个消息的生产者线程,多个消费者线程,并且每一条消息需要被所有的消费者都消费一次(这就不是一般队列,只消费一次的语义了),该怎么做? 这时仍然需要一个队列。但是: 1. 每个消费者需要自己维护一个指针,知道自己消费了队列中多少...

火狐下window.event获取undefined问题

火狐下用window.event来进行相应操作时,会显示undefined,其他浏览器可以, 解决方法: 1,传入对象 $("a").on("click",function(e){var event = e || window.event}); 2,不传入对象 $("a").on("click",function(){var event = argumen...

JS CustomEvent自定义事件传参

首先,看了鑫大佬的文章后,百度了文章内容的两个方法: 1、CustomEvent事件是有程序创建的,可以有任意自定义功能的事件 2、dispatchEvent()方法给节点分派一个合成事件 这两个方法之前也见过,不过并没有去了解,这次刚好又看到,就简单了解一下。好了,直接进入正文 一、addEventListener事件触发 例子,假设DOM对象变量名称是...

Web--js高级--11月30日随笔

一: 面向对象的三种方式: 1.单例模式 2.工厂模式 3.构造函数 js天生自带的类 Object 基类: Function Array Number Math Boolean Date Regexp String 二:事件 浏览器客户端上客户出发的行为都成为是事件 所有的事件都是天生自带的,不需要我们去绑定,只需要我们去触发。 通过 obj.事件名=...