事件中的几种实现方式
Dom0时代
1、直接在html的属性中写JS代码
1 <div onclick="alert(4);">Div1 Element</div>
2、定义一个函数,赋值给html元素的onXXX属性
1 <div onclick="clk()">Div Element</div> 2 <script type="text/javascript"> 3 function clk(){ 4 //.... 5 } 6 </script>
3、使用element.onXXX方式
1 <div id="d3">Div Element</div> 2 <script type="text/javascript"> 3 var d3 = document.getElementById('d3'); 4 d3.onclick = function(){ 5 //... 6 } 7 </script>
Dom2时代
4、添加事件方式,使用addEventListener或IE专有的attachEvent
事件流
官方的定义:事件按照从最特定的事件目标到最不特定的事件目标(document对象或者body)的顺序触发。
也可说,从页面中接收事件的顺序。也就是说当一个事件产生时,这个事件的传播过程,就是事件流。
事件不是单一的,比如:点击某个按钮,其实也点击了包含按钮的DIV、文档bod、document.
1 <body onclick="alert(3)"> 2 <div onclick="alert(2)"> 3 <button onclick="alert(1)">测试按钮</button> 4 </div> 5 </body>
在IE中,冒泡,会按这个顺序输出:1,2,3;
但在Netscape Navigator 4.0中则是‘反的’,它所支持的是捕获:输出3,2,1;
而DOM标准中事件流将这两种方式结合
window -> document -> body -> div -> button -> button -> div -> body -> document -> window;
这某些情况下,我们可能就需要去阻止事件流的传播:
1 function stopEvent (evt) { 2 var e = (evt != null) ? evt : window.event; 3 if (window.event) { 4 e.cancelBubble=true; // ie 5 } else { 6 e.stopPropagation(); // 标准组织 7 } 8 }
绑定、解绑、参数、事件对象在IE与W3C中的区别
1 Evt.extend({ 2 // 添加事件 3 on : function(ele,type, fn){ 4 if(document.addEventListener){ 5 ele.addEventListener(type, fn, false); 6 }else if(document.attachEvent){ 7 ele.attachEvent('on' + type, fn); 8 }else{ 9 ele['on' + type] = fn; 10 } 11 }, 12 // 解除事件 13 un : function(ele,type, fn){ 14 if(document.removeEventListener){ 15 ele.removeEventListener(type, fn); 16 }else if(document.detachEvent){ 17 ele.detachEvent(type, fn); 18 }else{ 19 ele['on' + type] = null; 20 } 21 }, 22 /*点击*/ 23 click : function(ele,fn){ 24 this.on(ele,'click',fn); 25 }, 26 // ... 27 });
Event接口(IE低版本浏览器不做专门的讨论)
JS里并没有严格的接口概念,只是为程序提供了某个对象拥有某些属性或者方法的描述
Event对象实现Event接口或子接口,声明了该种事件类型的详细信息。
其中Event是基础接口,UIEvent 和 MutationEvent是他的子接口。而MouseEvent又是UIEvent的子接口
Event 接口具有如下属性和方法:
Type 指明事件的类型
Target 发生事件的节点 // srcElement
currentTarget 事件当前传播到达的节点。
eventPhase 当前所处的事件传播阶段(捕获、目标、冒泡)
timeStamp 事件发生的时间点(时间戳)
cancelable 声明事件是否取消默认动作
bubbles 声明事件时候在文档中起泡
stopPorpagation() 阻止冒泡 // cancelBubble
preventDefault 阻止默认动作的执行
...
UIEvent接口属性
Event的子接口,在其基础上定义了两个新的属性:
view 发生事件的window对象
detail 提供事件的额外信息
MouseEvent 接口属性
是UIEvent的子接口,在UIEvent基础上定义了下列属性
button mousedown click 等事件中,鼠标键的状态(0鼠标左键2鼠标右键)
altKey ctrlKey metaKay shiftKey 在鼠标事件发生时。是否按下了该键
clientX Y 事件发生时,鼠标指针相对于浏览器左上角的坐标
screenXY 相对于显示器左上角的坐标
...
事件的代理与委托
通过事件的冒泡机制来实现的
优点:
1、是可以节省大量的内存占用,减少事件注册,比如在table上可以代理所有td的click事件
2、对新增的子对象不需要再次绑定事件,适于动态内容部分
缺点:
不能所有的事件都用代理,不应该触发的元素也被绑上了事件。
1 function delegate(pid, eventType, selector, fn) { 2 var parent = $$.$id(pid); 3 function handle(e){ 4 var target = $$.GetTarget(e); 5 console.log(target.nodeName) 6 if(target.nodeName.toLowerCase()=== selector || target.id === selector || target.className.indexOf(selector) != -1){ 7 fn.call(target); 8 } 9 } 10 parent[eventType]=handle; 11 } 12 delegate('table','onclick','td',function(){ 13 this.style.color='white' 14 this.style.background='red' 15 })
自定义事件
1 //将有参数的函数封装为无参数的函数 2 function createFunction(obj, strFunc) { 3 var args = []; //定义args 用于存储传递给事件处理程序的参数 4 if (!obj) obj = window; //如果是全局函数则obj=window; 5 //得到传递给事件处理程序的参数 6 for (var i = 2; i < arguments.length; i++){ 7 // alert(arguments[i]); 8 args.push(arguments[i]); 9 } 10 //用无参数函数封装事件处理程序的调用 11 return function() { 12 obj[strFunc].apply(obj, args); //将参数传递给指定的事件处理程序 13 } 14 } 15 function class1() { 16 } 17 class1.prototype = { 18 show: function() { 19 this.onShow(); 20 }, 21 onShow: function() { } 22 } 23 function objOnShow(userName) { 24 alert("hello," + userName); 25 } 26 function test() { 27 var obj = new class1(); 28 var userName = "test"; 29 obj.onShow = createFunction(null, "objOnShow", userName); 30 console.log(obj.onShow) 31 obj.show(); 32 } 33 test()