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.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.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 }
模拟事件暂时不须要,之后再细细道来