读javascript高级程序设计11-事件
一、事件流
事件流指从页面中接收事件的顺序。
1.事件冒泡(常用)
IE中采用的事件流是事件冒泡,先从具体的接收元素,然后逐步向上传播到不具体的元素。
2.事件捕获(少用)
Netscapte采用事件捕获,先由不具体的元素接收事件,最具体的节点最后才接收到事件。
3.DOM事件流
DOM2级事件包括三个阶段:事件捕获阶段、处于目标阶段和事件冒泡阶段。
二、事件处理程序
事件处理程序就是响应某些事件的函数,如onclick等。
1. DOM0级事件处理程序
每个元素都有自己的事件处理程序属性,如onclick等。可以通过js将一个函数赋值给元素的事件处理程序属性。
在DOM0事件处理程序中,事件处理程序里的this指向当前元素。
var objlogo=document.getElementById("site_nav_top"); objlogo.onclick=function(){ alert(this.innerHTML);//代码改变世界 }
删除DOM0事件,只需将事件处理程序的值赋为null即可。
objlogo.οnclick=null;
2. DOM2级事件处理程序
DOM2有两个方法用来添加和移除事件处理程序:addEventListener()和removeEventListener()。它们都有三个参数:第一个参数是事件名(如click);第二个参数是事件处理程序函数;第三个参数如果是true则表示在捕获阶段调用,为false表示在冒泡阶段调用。
- addEventListener():可以为元素添加多个事件处理程序,触发时会按照添加顺序依次调用。
- removeEventListener():不能移除匿名添加的函数。
//不能移除 var obj = document.getElementById('site_nav_top');obj.addEventListener('click', function () { alert(this.innerHTML);}, false);obj.removeEventListener('click', function () { alert(this.innerHTML);}, false);//能移除 var obj=document.getElementById("site_nav_top"); var show=function(){ alert(this.innerHTML); } obj.addEventListener("click",show,false); obj.removeEventListener("click",show,false);
3.IE事件处理程序
IE的事件处理程序也有两个类似的方法:attachEvent()和detachEvent()。它们有两个参数:第一个是事件名(如onlick);第二个参数是事件处理程序的函数。
注意:
- 事件名前面有on前缀;
- 在事件处理程序的函数中,this不再指向当前元素,而是指向window对象。
var obj=document.getElementById("site_nav_top"); var show=function(){ alert(obj.innerHTML); } obj.attachEvent("onclick",show); obj.detachEvent("onclick",show);
4.跨浏览器的事件处理程序
综合前面几种情况,进行浏览器能力检测,就可以写出跨浏览器的事件处理程序了.
EventUtil = {addHandler: function (obj, event, handler) {if (obj.addEventListener) {obj.addEventListener(event, handler, false);} else if (obj.attachEvent) {obj.attachEvent('on' + event, handler);} else {obj['on' + event] = handler;}},removeHandler: function (obj, event, handler) {if (obj.removeEventListener) {obj.removeEventListener(event, handler, false);} else if (obj.detachEvent) {obj.detachEvent('on' + event, handler);} else {obj['on' + event] = null;}} };
var obj = document.getElementById('site_nav_top'); var show = function () {alert(obj.innerHTML); }EventUtil.addHandler(obj, 'click', show); EventUtil.removeHandler(obj, 'click', show);
三、事件对象
当触发DOM事件时,会产生一个事件对象event。不同浏览器对该对象的支持略有不同。
1.DOM中的事件对象
在支持DOM0或DOM2的浏览器中,会将event对象传入到事件处理程序中。
var obj=document.getElementById("site_nav_top"); var show=function(event){ alert(event.type); } obj.addEventListener("click",show,false);//点击运行结果 click
event对象包含于创建它的事件对象相关的属性和方法。几种常用属性和方法:
① this, currentTarget 与 target:
event.this与event.currentTarget始终相等,表示事件处理程序当前正在处理的元素;
event.target表示事件的实际目标元素。
var obj=document.getElementById("site_nav_top"); var show=function(event){console.log(this);console.log(event.currentTarget);console.log(event.target); } obj.addEventListener("click",show,false); //点击头部“代码改变世界”结果 <div id="site_nav_top">,<div id="site_nav_top">,<div id="site_nav_top"> var show=function(event){console.log(this);console.log(event.currentTarget);console.log(event.target); } document.body.addEventListener("click",show,false); //点击头部“代码改变世界”结果: <body>, <body>, <div id="site_nav_top">
②event.type:被触发的事件类型,如click。通过判断该属性,可以用一个函数中处理多个事件。
var obj=document.getElementById("nav_menu"); var handler=function(event){switch(event.type){case "mouseover":event.target.style.backgroundColor="red";break;case "mouseout":event.target.style.backgroundColor="";break;case "click":alert("click menu");break;} } obj.addEventListener("click",handler,false); obj.addEventListener("mouseover",handler,false); obj.addEventListener("mouseout",handler,false);
③event.preventDefault():阻止事件的默认行为。
例如在上面的例子中,单击站点导航条在弹出“click menu”后,仍然打开了链接。如果想阻止其默认行为,可以这样处理:
case "click":alert('click menu')event.preventDefault();break;
④event.stopPropagation():阻止事件进一步冒泡或捕获。
var obj = document.getElementById('nav_menu'); var handler = function (event) {alert('handler'); } var handler1 = function (event) {alert('handler1'); } obj.addEventListener('click', handler, false); document.body.addEventListener('click', handler1, false);
在这个例子中给菜单和body分别添加了单击事件,当点击菜单时会出现两次弹窗。如果想阻止事件冒泡,可以做如下修改:
var handler=function(event){alert('handler');event.stopPropagation(); }
2. IE中的事件对象
①event对象
使用DOM0添加的事件处理程序,event作为window对象的属性存在。
var obj=document.getElementById("nav_menu"); obj.onclick=function(event){ alert(window.event.type); }
使用attachEvent添加的事件处理程序,可以将event作为函数的参数传入,也可以直接使用window.event。
var obj=document.getElementById("nav_menu"); obj.attachEvent("onclick",function(event){ alert(event.type); alert(window.event.type); });
②event.srcElement:事件的目标元素,等同于DOM中的target属性。
③event.returnValue:将该属性设置为false可以阻止默认事件。相当于DOM中的preventDefault()。
④event.cancelBubble:将该属性设为true可以阻止事件冒泡。相当于DOM中的 stopPropagation()。
3.跨浏览器的事件对象
综合考虑DOM和IE中的事件对象,写出跨浏览器的事件对象,放在之前的EventUtil中。
EventUtil = { addHandler: function (obj, event, handler) {......},removeHandler: function (obj, event, handler) { ......},getEvent: function (event) {return event ? event : window.event;},getTarget: function (event) {return event.target || event.srcElement;},preventDefault: function (event) {if (event.preventDefault) {event.preventDefault();} else {event.returnValue = false;}},stopPropagation: function (event) {if (event.stopPropation) {event.stopPropation();} else {event.cancelBubble = true;}} }; //以园子首页菜单栏为例调用 var obj = document.getElementById('nav_menu'); EventUtil.addHandler(obj, 'click', function (event) {var event = EventUtil.getEvent(event);var target = EventUtil.getTarget(event);alert(target);EventUtil.preventDefault(event);EventUtil.stopPropagation(event); }); EventUtil.addHandler(document.body, 'click', function () {alert('body'); })
四、事件类型
1.load事件
load可以用来判断图片加载完毕。注意:新创建的图像元素不是在加载到页面中才开始下载,而是设置src之后就开始下载。
var obj = document.getElementById('site_nav_top'); EventUtil.addHandler(obj, 'click', function () {var img = new Image();EventUtil.addHandler(img, 'load', function () {alert('load');});img.src = 'http://static.cnblogs.com/images/logo_small.gif';obj.appendChild(img); })
load可以用来判断js加载完成。<script>元素可以触发load事件,来判断动态加载的js文件是否加载完成。它和img不同,必须设置了src属性并且添加到文档之后才会开始下载。
EventUtil.addHandler(document.body,"click",function(){ var script=document.createElement("script");EventUtil.addHandler(script,"load",function(){alert('load');});script.src="http://common.cnblogs.com/script/jquery.js";document.body.appendChild(script); })
2.resize事件:当浏览器的宽度或高度变化时触发该事件。有些浏览器窗口变化1像素时就触发该事件,有的浏览器在停止调整窗口大小时才出发该事件。因此不要在该方法中写大量的计算代码,以免减缓浏览器速度。
3.获取鼠标位置
- clientX和clientY:客户区坐标位置。表示鼠标在视口中的水平位置和垂直位置。
- pageX和pageY:页面坐标位置。表示鼠标在页面中的位置,从页面本身而不是视口的左边和顶部开始计算的。
- screenX和screenY:屏幕坐标位置。鼠标指针相对于整个屏幕的坐标位置。
var obj = document.getElementById('headline_block'); EventUtil.addHandler(obj, 'click', function (event) {var result = event.clientX + ',' + event.clientY + '\r\n';result += event.pageX + ',' + event.pageY+'\r\n';result+=event.screenX+','+event.screenY;alert(result); })
4.beforeunload事件
事件在浏览器卸载页面之前触发,可以通过它来取消卸载并继续使用原来的页面。
要在卸载页面时显示弹窗提示,需要将event.returnValue设置为提示语,并且将该提示语作为函数的返回值。
EventUtil.addHandler(window,'beforeunload',function(event){ event=EventUtil.getEvent(event);var msg='确认关闭吗';event.returnValue=msg;return msg; });
五、内存和性能
1.事件委托
事件委托可以解决页面中事件处理程序过多的问题。事件委托利用了事件冒泡,只指定一个事件处理程序,就可以处理某一类型的所有事件。
EventUtil.addHandler(document.body, 'click', function (event) {event = EventUtil.getEvent(event);var target = EventUtil.getTarget(event);switch (target.id) {case 'site_nav_top':alert('口号');break;case 'nav_menu':alert('点击菜单');EventUtil.preventDefault(event);break;case 'editor_pick_lnk':alert('推荐区');EventUtil.preventDefault(event);break;} });
2.移除事件处理程序
如果内存中保留大量无用的事件处理程序,会影响性能。所以一定要在不需要的时候及时移除事件处理程序。尤其注意以下情况:
使用innerHTML删除带有事件处理程序的元素时,要先将事件处理程序设置为null。使用委托也可以解决这个问题,不直接将事件加载会被innerHTML替换的元素,而是将事件赋给其父元素,这样就可以避免了。
卸载页面时,最好手工清除所有的事件处理程序。
六、DOM中的事件模拟
1. DOM中的事件模拟分三步:
- 使用document.createEvent()创建event对象。通过赋值不同的参数,可以模拟不同的事件类型
- 初始化event对象;
- 触发事件,调用dispatchEvent()方法,所有支持事件的DOM节点都可以支持这个方法。
2. 模拟鼠标事件
首先createEvent()方法传入参数是“MouseEvent”来模拟鼠标事件。
返回的event对象有一个initMouseEvent()方法,用来初始化事件信息。该方法有15个参数:
- type(字符串):要触发的事件类型,比如“click”。
- bubbles(bool):事件是否冒泡。一般设为true。
- cancelable(bool):事件是否可以取消。一般设为true。
- view:与事件关联的视图,一般设置为document.defaultView。
- detail(整数):与事件有关的详细信息,一般设置为0.
- screenX:事件相对于屏幕的X坐标。
- screenY:事件相对于屏幕的Y坐标。
- clientX:事件相对于视口的X坐标。
- clientY:事件相对于视口的Y坐标。
- ctrlKey(bool):是否俺下了Ctrl键,默认为false。
- altKey:是否按下了alt键,默认false。
- shiftKey:是否按下了shift键,默认false。
- metaKey:是否按下了meta键,默认false.
- button(整数):按下了哪个鼠标键,默认0。
- relatedTarget:与事件相关的对象,一般为null.只在模拟mouseover和mouseout的时候会用到。
最后给DOM元素调用dispatchEvent()方法来触发事件。
//执行位置博客园首页 var objmenu = document.getElementById('nav_menu'); objmenu.onclick = function () {console.log('menu'); } document.body.onclick = function () {console.log('body'); } var event = document.createEvent('MouseEvent'); event.initMouseEvent('click', true, true, document.defaultView, 0, 0, 0, 0, 0, false, false, false, false, 0, null); for (var i = 0; i < 5; i++) {objmenu.dispatchEvent(event); }
3. 自定义DOM事件
DOM3中支持自定义DOM事件。要创建新的自定义事件,可以调用document.createEvent()方法,返回的对象有一个initCustomEvent()方法,包含四个参数:
- type:触发事件的类型;
- bubbles:事件是否冒泡;
- cancelable:事件是否可以取消;
- detail:任意值,保存在event.detail属性中。
最后在DOM元素调用dispatchEvent()方法触发事件。
var objmenu = document.getElementById('nav_menu'); EventUtil.addHandler(objmenu, 'myevent', function (event) {console.log('menu' + event.detail); }); EventUtil.addHandler(document.body, 'myevent', function (event) {console.log('body' + event.detail); }) if (document.implementation.hasFeature('CustomEvents', '3.0')) {var event = document.createEvent('CustomEvent');event.initCustomEvent('myevent', true, true, '测试事件detail');for (var i = 0; i < 5; i++) {objmenu.dispatchEvent(event);} }
转载于:https://www.cnblogs.com/janes/p/3912677.html
读javascript高级程序设计11-事件相关推荐
- 读javascript高级程序设计-目录
javascript高级编程读书笔记系列,也是本砖头书.感觉js是一种很好上手的语言,不过本书细细读来发现了很多之前不了解的细节,受益良多.<br/> 本笔记是为了方便日后查阅,仅作学习交 ...
- 读javascript高级程序设计10-DOM
一.节点关系 元素的childNodes属性来表示其所有子节点,它是一个NodeList对象,会随着DOM结构的变化动态变化. hasChildNodes():是否有子节点. var headline ...
- 读javascript高级程序设计15-Ajax,CORS,JSONP,Img Ping
平时用惯了jQuery.ajax之类的方法,却时常忽略了它背后的实现,本文是学习了AJAX基础及几种跨域解决方案之后的一些收获. 一.AJAX--XMLHttpRequest 谈起Ajax我们都很熟悉 ...
- 读javascript高级程序设计13-JSON
JSON是一个轻量级的数据格式,可以简化表示数据结构的工作量.在实际工作中,我们经常用它来传递数据,不过对于其使用的一些细节还是需要注意的.在ECMAScript5中定义了原生的JSON对象,可以用来 ...
- 读javascript高级程序设计12-HTML5脚本编程
一.跨文档消息传递(XDM) 1.发送消息 postMessage(msg,domain)用于发送跨文档消息.第一个参数是要传递的消息内容,第二个参数表示接收方来自哪个域.第二个参数有助于提高安全性, ...
- javascript高级程序设计---js事件思维导图
绘制思维软件与平时用的笔记,以及导出功能,这三个问题综合起来,于是我把思维导图分开画 1.js事件的基本概念 2.js事件的事件处理程序 3.js事件的事件对象 转载于:https://www.cnb ...
- JavaScript高级程序设计笔记 事件冒泡和事件捕获
1.事件冒泡 要理解事件冒泡,就得先知道事件流.事件流描述的是从页面接收事件的顺序,比如如下的代码: <body><div> click me!</div> < ...
- 读javascript高级程序设计02-变量作用域
一. 延长作用域链 有些语句可以在作用域前端临时增加一个变量对象,该变量对象在代码执行完成后会被移除. ①with语句延长作用域. function buildUrl(){ var qs=" ...
- 读javascript高级程序设计03-函数表达式、闭包、私有变量
一.函数声明和函数表达式 定义函数有两种方式:函数声明和函数表达式.它们之间一个重要的区别是函数提升. 1.函数声明会进行函数提升,所以函数调用在函数声明之前也不会报错: test(); functi ...
最新文章
- IDEA spring boot maven架包
- 某公司的网络管理员职责
- 用php怎么输出饼状图,php绘图之生成饼状图的方法_PHP
- rust 案例_RUST-X气相防锈产品落户中国,助力中国高端制造出口海外
- 诗和远方:无题(四十七)
- swfobject.js 2.2简单使用方法
- 光环PMP 项目范围管理 、项目进度管理、项目成本管理、项目质量管理
- BPM波导matlab,用Matlab画平板波导色散图详解.doc
- 笔记本电脑频繁自动重启_笔记本电脑经常自动重启怎么办
- 如何用python计算增长率_如何用excel函数来计算增长率?
- win10自带微软拼音输入法卡死卡顿解决方法汇总
- string类型与date类型转换
- java-php-net-python-基于的相册软件的设计与实现计算机毕业设计程序
- 随便记录一下:微信公众号后台管理系统,获取需要扫描的二维码
- 优秀的教育网站、自学网站、教师网站
- 润乾——润乾报表错误
- 计算机右击加设备管理器,win10系统计算机右键菜单添加设备管理器的还原步骤...
- 数据分析-数据类型及数据收集和整理方法-04
- 大学计算机基础的教案,《大学计算机基础》教案.docx
- 我的电磁学讲义10:磁感应强度 毕奥-萨伐尔定律