事件

来源:互联网 发布:邮箱服务器搭建软件 编辑:程序博客网 时间:2024/05/03 07:37

事件流

事件流:从页面接收事件的顺序
IE和Netscape提出了完全相反的事件流概念

事件冒泡(IE)

点击事件会沿着dom树向上传递
例如:div->body->html->document

事件捕获(NetScape)

点击事件沿着dom树向下传递
例如:document->html->body->div

现在主流的都是支持事件冒泡

dom事件流

dom2将事件流分为三个阶段:捕获阶段,处理阶段,冒泡阶段
即使dom2明确要求捕获阶段不应该涉及事件目标,但是在很多浏览器上都会在捕获阶段触发目标事件。
于是,有两个阶段可以在目标对象上操作事件

事件处理程序

事件处理程序名称=on+事件名称(click,load)

html事件处理程序

事件处理程序有权访问 全局环境中的所有代码

<input type = 'button' value='clickMe' onclick='alert('click')'>

这里我访问一个全局变量myname:

<body><script type="text/javascript">    var myname = 'geguo';</script><input type="button" value="clickMe" onclick="console.log(myname)"></body>

每点击一下 控制台输出 geguo

事件对象
在元素(input)中定义一个事件处理程序有一个好处,可以获取到元素的所有属性,这些属性都会封装到一个函数中(this指向这个函数对象,事件处理程序中可以直接访问),这个函数有一个局部变量,也就是事件对象;这个事件对象event是默认创建的,可以在事件处理程序中直接访问。

dom0事件处理程序

在Js代码中添加事件处理程序,当js没有被执行到的时候,点击不会反应。

<input type="button" value="clickMe"><script type="text/javascript"> var mbts = document.getElementsByTagName('input'); var mb=mbts[0]; mb.onclick=function(){    console.log(this.value); };</script>

这里的this指向的是元素对象(该对象中有一个event属性值就是事件对象)
删除处理程序: mb.onclick=null;

Dom2级事件处理程序

上述两种方法有一个明显的缺点:click事件只能添加一个事件处理程序,然而DOM2可以为同一事件添加多个处理程序

  • addEventListener(‘事件名称(非事件处理程序名称)’,事件处理程序(函数),boolan(true捕获阶段处理|false冒泡阶段处理))共三个参数
  • removeEventListener(‘事件名称’,之前添加的处理函数,boolean)
  • 第三个参数一般是false,通常建议通过冒泡方式处理
<input type="button" value="clickMe"><script type="text/javascript"> var mbts = document.getElementsByTagName('input'); var mb=mbts[0];var handle = function(){    console.log(this.value); }; mb.addEventListener('click',handle,false); // mb.addEventListener('click',handle2,false);还可以添加一个函数 //移除后点击没有反应了;注意这里的事件处理函数是同一个函数对象 mb.removeEventListener('click',handle,false);</script>

IE事件处理程序

支持IE事件处理程序的只要IE和Opera

  • attachEvent(’事件处理程序名’(非事件名),处理函数);
  • detachEvent(同上)

与dom2级处理程序的区别在于:

  1. attach方式支持的浏览器只有两种
  2. 它们的第一个参数不同
    相同点:
    他们都支持添加多个事件处理程序,不过执行的顺序与添加的顺序不同。
<input type="button" value="clickMe"><script type="text/javascript"> var mbts = document.getElementsByTagName('input'); var mb=mbts[0];var handle = function(){    console.log(this.value); }; mb.attachEvent('onclick',handle);

Chrome根本不支持attachEvent()

在 IE 中使用 attachEvent() 与使用 DOM0 级方法的主要区别

主要在于事件处理程序的作用域。
在使用 DOM0 级方法的情况下,事件处理程序会在其所属元素的作用域内运行
在使用 attachEvent() 方法的情况下,事件处理程序会在全局作用域中运行,因此 this 等于 window 。

兼容浏览器事件处理工具类

默认使用dom0
最先检测dom2
其次判断IE

var EventUtil={  addHandler:function(element,type,handle){    if (element.addEventListener) {        element.addEventListener(type,handle,false);    }else if(element.attachEvent){        element.attachEvent('on'+type,handle);    }else{        element['on'+type]=handle;    }  },  removeHandle:function(){        if (element.addEventListener) {        element.removeEventListener(type,handle,false);    }else if(element.attachEvent){        element.detachEvent('on'+type,handle);    }else{        element['on'+type]=null;    }  }};EventUtil.addHandler(mb,'click',handl);

事件对象

var handl = function(){    //this指向元素所在作用域对象    console.log(this.value);    // 这里的event 可以直接访问    console.log(event.type);    // 默认的事件处理程序的第一个参数也是事件对象    console.log(arguments[0].type); };

兼容DOM的浏览器会将一个event对象作为事件处理程序的第0个参数传入。

  1. 在事件处理程序中可以直接访问event对象(event作为window的属性)
  2. arguments[0]其实就是event对象
  3. 可以将event对象传入:function(event){ event.type}

event对象的成员属性

target Element类型:事件的目标(具体哪个元素的事件)
type string类型:事件类型(click,move)
currentTarget Element类型:当前正在处理事件的那个元素
stopPropagation 阻止传递
preventDefault 取消事件

//将点击事件添加到body上EventUtil.addHandler(document.body,'click',handle);
var handle = function(event){    console.log(event.currentTarget === document.body);    console.log(this === document.body);    console.log(event.targt === mb);

因为事件处理程序都注册在body上,所以this和currentTarget都指向body元素,而真正的目标targe是指向button(我怎么测试不是呢?)

IE中的Event对象

  • type
  • srcElement dom中的target
  • returnValue 取消事件
  • cancelBubble 取消事件冒泡

IE中访问event对象

  1. dom0级事件只能通过window.event 访问
  2. dom2级事件可以通过event参数去访问
  3. IE中没有内置event对象
<script type="text/javascript">    var btn = document.getElementById('button');    // IE 中DOM0级事件访问event只能通过window.event    btn.onclick = function(){      var event = window.event;//在DOM0中需要如此访问      alert(event.type); //"click" 直接访问无效    };    //  这是DOM2级    btn.attachEvent("onclick", function(event){       alert(event.type);    });</script>

跨浏览器事件对象

因为IE浏览器和其他浏览器的属性不一样,所以需要封装一个类来专门处理他们之间的不同

var EventUtil={  addHandler:function(element,type,handle){    if (element.addEventListener) {        element.addEventListener(type,handle,false);    }else if(element.attachEvent){        element.attachEvent('on'+type,handle);    }else{        element['on'+type]=handle;    }  },  removeHandle:function(element,type,handle){        if (element.addEventListener) {        element.removeEventListener(type,handle,false);    }else if(element.attachEvent){        element.detachEvent('on'+type,handle);    }else{        element['on'+type]=null;    }  },  getEvent:function(event){    //IE 的dom0事件只支持window.event,不支持通过参数传递    //IE的dom2和其他浏览器都支持通过event参数方式访问    return event?event:window.event;  },  getTarge:function(event){    // IE 的dom0 不支持event参数方式访问    // return event.targt||event.srcElement;    return this.getEvent(event).targt||this.getEvent(event).srcElement;  },  // 取消该事件(和移除该事件有什么不一样么)  preventDefault:function(event){    var event = this.getEvent(event);    if (event.preventDefault){    event.preventDefault();    } else {        //IE中的        event.returnValue = false;    }  },  // 阻止事件冒泡  stopPropagation:function(event){    var event = this.getEvent(event);    if (event.stopPropagation) {        event.stopPropagation();    }else{        event.cancelBubble = true;    };  }};

这个工具类如何使用

DOM0级事件

 mb.onclick=function(event){    var type =EventUtil.getTarge(event).type;    alert(type); }

DOM2级事件

EventUtil.addHandler(mb,'click',function(event){    var type=EventUtil.getTarge(event).type;    alert(type);}) 

在IE和Chrome浏览器中测试均有效;

事件类型

UI事件

焦点事件

鼠标与滚轮事件

键盘与文本事件

复合事件

变动事件

HTML5事件

设备事件

触摸与手势事件

性能与优化

添加过多的函数会占用过大的内存,同时也会影响页面加载的速度
利用事件冒泡的特性,可以通过一个事件处理程序来处理某一类型的事件;

<ul id="myLinks"><li id="goSomewhere">Go somewhere</li><li id="doSomething">Do something</li><li id="sayHi">Say hi</li></ul>

要给三个item添加点击事件传统写法:

var item1 = document.getElementById("goSomewhere");var item2 = document.getElementById("doSomething");var item3 = document.getElementById("sayHi");EventUtil.addHandler(item1, "click", function(event){location.href = "http://www.wrox.com";});EventUtil.addHandler(item2, "click", function(event){document.title = "I changed the document's title";});EventUtil.addHandler(item3, "click", function(event){alert("hi");});

这有一个明显缺点:代码冗余
使用代理方式可以解决这个问题:

var list = document.getElementById("myLinks");EventUtil.addHandler(list, "click", function(event){event = EventUtil.getEvent(event);var target = EventUtil.getTarget(event);switch(target.id){case "doSomething":document.title = "I changed the document's title";break;case "goSomewhere":location.href = "http://www.wrox.com";break;case "sayHi":alert("hi");break;}});

尽量在dom书最高层次的节点上添加该点击事件。
这里的target就是用户通过鼠标点击的那个控件,通过冒泡会传递到父节点上,父节点会处理。事件被处理后还会继续冒泡么?

移除事件处理程序

如果知道某个元素即将被移除那些请先移除它的事件处理程序

<div id="myDiv"><input type="button" value="Click Me" id="myBtn"></div><script type="text/javascript">var btn = document.getElementById("myBtn");btn.onclick = function(){//先执行某些操作document.getElementById("myDiv").innerHTML = "Processing..."; //麻烦了!};</script>

以上:当按钮点击时在自己的处理程序中把自己移除了
这种做法,虽然移除了按钮元素,但是事件处理程序依然在元素的作用域中运行,持有这个元素的引用。导致该元素无法被真正的释放。

正确的写法应该是:

btn.onclick = function(){//先执行某些操作btn.onclick = null; // 移除事件处理程序document.getElementById("myDiv").innerHTML = "Processing...";};
0 0
原创粉丝点击