js与HTML之间的交互通过事件实现的。
事件流:描述从页面接受事件的顺序
● IE事件流——事件冒泡流 从文档中嵌套层次最深的那个节点开始接受 (常用)
● Netscape Communicator的事件流——事件捕获流
1。DOM事件 规定的事件流包括3各阶段:时间捕获阶段,处于目标阶段和事件冒泡阶段
DOM2级事件规范要求捕获阶段不会涉及到事件目标,但在IE9,Safari,Chrome,Firefox和Opera 9.5中都会在捕获阶段触发事件对象上的事件,结果,有两次机会在目标对象上操作事件
2. DOM0级事件处理程序
就是将一个函数赋值给一个事件处理程序属性(如click load mouseover 就是事件处理程序)
DOM0级对每个事件只支持一个事件处理程序
<input type="button" value="click me" onclick="alert(this.value);">
3.DOM2级事件处理程序
/* *DOM2级事件 定义了两个方法,用于处理指定和删除事件处理程序: addEventListener()和removeEventListener() 接受3个参数:要处理的事件名,事件处理程序的函数,一个布尔值 布尔值为true 表示在捕获阶段调用事件处理程序 布尔值为false 表示在冒泡阶段调用事件处理程序(一般是false) */ var btn=document.getElementById("myBtn"); btn.addEventListener("click",function(){ alert(this.id); },false); // DOM2级方法添加事件处理程序好处:可以添加多个事件处理程序 触发是按代码先后顺序 // 通过addEventListener()添加的事件处理程序只能使用removeEventlistener()来移除 // 注意:通过addEventlistener()添加的匿名函数无法移除 // 正确的代码 把匿名函数赋给一个变量 通过变量指定 var btn=document.getElementById('myBtn'); var handler=function(){ alert(this.id); }; btn.addEventListener("click",handler,false); // 这里省略其他代码 btn.removeEventListener("click",handler,false);//有效 大多数情况,都是将事件处理程序添加到事件冒泡阶段(第三个参数为false) // 跨浏览器的事件处理程序 创建一个EventUtil对象 /* addHandler() 与removeHandler() 接受3个参数:要操作的元素。事件名称,和事件处理程序函数 */ var EventUtil = { addHandler: function (element, type, handler) { if (element.addEventListener) { element.addEventListenr(type, handler, false); } else if (element.attachEvent) { element.attachEvent("on" + type, handler); } else { element["on" + type] = handler; } }, removeHandler: function (element, type, handler) { if (element.addEventListener) { element.removeEventListener(type, handler, false); } else if (element.attachEvent) { element.detachEvent("on" + type, handler); } else { element["on" + type] = null; } } }; var btn=document.getElementById('myBtn'); var handler=function(){ alert('clicked'); }; EventUtil.addHandler(btn,"click",handler); // 这里省略了其他代码 EventUtil.removeHandler(btn,"click",handler);
4.事件对象
在触发DOM上的某个事件时,会产生一个事件对象event。
这个对象包含所有与事件有关的信息
event对象包含的属性和方法(均为只读)
属性/方法 类型 说明
● bubbles Boolean 表明事件是否冒泡
● cancleable Boolean 是否可以取消事件的默认行为
● currentTarget element 指向当前的那个元素
● dedaultPrevented Boolean 为true 表示已调用preventDefault()
● datail Integer(整数) 事件相关的细节信息
● eventPhase integer 事件处理程序的阶段:1表示捕获阶段 2 处于目标阶段 3 表示事件冒泡阶段
● preventDefault() function 取消事件的默认行为 cancleable为true可以调用它
● stopImmediatePropagation() 取消事件进一步捕获和冒泡,同时阻止事件处理程序被调用
● stopPropagation() 取消事件进一步捕获和冒泡 当bubbles为true调用它
● target element 事件的目标
● trusted boolean true表示浏览器生成
● type String 被触发的事件类型
● view AbstractView
在事件处理程序函数内部,对象this始终等于 currentTarget的值
// 避免触发注册在document.body上的事件处理程序 var btn=document.getElementById("myBtn"); btn.onclick=function(event){ alert('clicked'); event.stopPropagation(); }; document.body.onclick=function(event){ // alert("body clicked"); alert(event.eventPhase);//3 处于事件冒泡阶段 }
只有在事件处理程序执行期间,event对象才存在,一旦事件处理程序执行完毕,event对象就会被销毁
在IE中,event参数是未定义的(undefined),因此就会返回window.event
5 事件类型
DOM3规定了一下几类事件:
1. UI(user interface 用户界面)事件:用户与页面元素交互时触发
load 当页面加载完成(包括所有图像,js文件,css文件等外部资源)触发window上面的load事件
2. 焦点事件
3. 鼠标事件
4. 滚轮事件
5. 键盘事件
6. 合成事件:当为IME(input method editor)输入字符时触发
7. 受动(mutation)事件:当底层DOM结构发生改变时触发
EventUtil.addHandler(window,"load",function(event){ alert('load'); });
5.1 根据DOM2的规范:应该在document而非window上面触发load事件,当时所有浏览器都在window上实现了load,来保证向后兼容
5.2 unload事件 只要用户从一个界面切换到另一个界面,就会发生unload事件-——unload事件主要用来清楚引用,以避免内存泄漏(注意 其实这个事件是在body上触发的,不是window上,但为了向后兼容)
window.addEventListener('unload',function(event){ alert('unload'); },false);
5.3 resize事件
当浏览器窗口大小发生改变时发生resize事件。(不要再这个事件中加入大计算量的代码 )
5.4 scroll事件 滚动
焦点事件:
blur 元素 失去焦点时触发
focus 元素活得焦点
鼠标与滚动事件
click dblclick (mousedown按下鼠标按钮时触发 mouseup)
鼠标滚轮事件 mousewheel
在event中clientX clientY储存点击的位置信息
在没有滚动的情况下 pageX的值=clientX pageY的值=clientY
屏幕坐标位置 ——是相对于电脑屏幕的 screenX和screenY
event.keyCode ——键盘操作所对应ASCII码
setTimeout(function(){ //在此添加事件处理程序 },0);//表示在当前js处理完成后立即运行这个函数 // hashchange url参数列表发生变化时触发 在ajax中用来保存状态或导航信息 window.addEventListener('hashchange',function(event){ alert("old URL="+event.oldURL+"; new URL="+event.newURL); },false);
6. 事件委托—— 解决事件处理程序过多的问题,利用事件冒泡
只需在DOM树中尽量最高的层次上添加一个事件处理程序(而不用为树下每一个子元素添加事件处理程序)
每个函数都是对象,都会占用内存,内存中对象越多,性能就会越差
事件委托的优点:
● document对象很快就能访问到
● 在页面中设置事件处理程序所需的时间少
● 整个页面占用的内存小
/*
内存优化——事件委托
<ul id="mylinks"> <li id="goSomewhere"> go goSomewhere</li> <li id="doSomething">doSomething</li> <li id="sayHI">sayHI</li> </ul>
对于ul元素每一项添加点击事件
*/ (function () { var list = document.getElementById('mylinks'); list.addEventlistener('click', function (event) { switch (event.id) { case "goSomewhere": location.href = 'http://www.wrox.com'; break; case "doSomething": document.title = "i change the document's title"; break; case "sayHI": alert('hi'); break; } }, false); })();
6.1 移除事件处理程序: 两种情况
● 删除了元素,但元素相关的事件处理程序还一直在内存中, 解除引用 设置为null
● 在页面被卸载之前没有清理干净事件处理程序,他就会滞留在内存中,尤其实在两个界面来回切换时(或者刷新时),内存中的对象数目就会增加
7.模拟事件
用js在任意时刻触发特定的事件,在测试web应用程序时极其有用
DOM中事件模拟 在document上创建 createEvent () 接受一个参数 需要创建事件的字符串类型:
● UIevents 一般的UI事件 鼠标 键盘事件继承自UI事件 DOM3中UIevent
● MouseEvents 鼠标事件 DOM3级中时MouseEvent
● MutationEvents一般的DOM变动事件 DOM3中时MutationEvent
● HTMLevents 一般的HTML事件
// 模拟鼠标事件 var btn=document.getElementById('myBtn'); // 创建事件对象 var event=document.createEvent('MouseEvents'); // 初始化事件对象 event.initMouseEvent("click",true,true,document.defaultView,0,0,0,0,0,false,false,false,false,0,null); // 触发事件 btn.dispatchEvent(event);