js 事件
2015-05-24 11:57
281 查看
今天来总结一下js事件的相关知识^_^
首先要明白什么是事件流。事件流大致分为3个阶段:事件捕获阶段、处于目标阶段、事件冒泡阶段。ie8及其以下没有事件捕获阶段,只有后面两个阶段
事件捕获:事件从目标从上往下进行传播,从外往内传播。
事件冒泡:事件从目标从下往上进行传播,从内往外传播。
二者刚好相反,这样说太抽象了,下面的图片应该能直观的体现
接下来是最基本的,添加事件和删除事件
而最普通的方法如下:
下面是比较高端的用法:
addEventListener() 和 removeEventListener()
这是比较高端的用法,都需要接收3个参数,ie8及其以下不支持这种方式
第一个参数是事件的类型,第二个参数是对应的handler,第三个判断是否在冒泡阶段处理
为true,表示在捕获阶段处理, false表示在冒泡阶段处理事件
IE不支持在捕获阶段处理事件,为了兼容性考虑,通常选择在冒泡阶段处理事件
只是ie8及其以下不支持这种方式,不过同时提供了另一种方式
attachEvent()和detachEvent()
既然这里存在浏览器的兼容性问题,我们为什么不用一个方法将它们的差异封装起来,方便用户使用呢?
那就换一种封装的方式:
下面来看一下event 对象
标准浏览器中:
target 指向鼠标操作的元素;currentTarget 指向添加事件的元素,也就是this
这里有两个例子,大家可以亲手测试一下,点击的区域不同,产生的结果不一样
下面针对事件冒泡举个例子:
从这里也可以体会出事件冒泡的机理
阻止默认行为
标准浏览器是preventDefault(),IE是returnValue = false
同时这里要注意,IE和标准浏览器获取event的方式不一样
阻止冒泡
标准浏览器是stopPropagation(),IE是cancelBubble = true
1.IE和标准浏览器在event的获取上有差异
2.IE中没有标准浏览器中的target属性,但是有srcElement属性作为替代
3.IE中阻止默认行为会用到returnValue这个属性,false则取消默认行为。标准浏览器用preventDefault()
4.IE中取消事件冒泡会用到cancelBubble这个属性,为true会取消冒泡。标准浏览器用stopPropagation()
既然IE与标准浏览器在这么多地方存在差异,我们何不将之封装起来,让用户体会不到差异不是很好吗?
最后简单来说说事件代理(event delegation)
通过事件代理,可以把事件处理器添加到一个父级元素上,等待一个事件从它的子级元
素里冒泡上来,并且可以得知这个事件是从哪个元素开始的。这样就避免了把事件处理器
添加到多个子级元素上,提高了性能。
比如我们有一张数据量很大的html表格,现在有一个需求,用户通过鼠标能够对每一个单元格中的数据进行更改。
如果针对很一个单元格都添加一个事件将产生很大的性能问题,甚至是浏览器崩溃。如果在这里使用事件代理,我
们只需要把事件添加到table元素上面,并且判断出是哪个单元格被操作了,然后进行相应的处理,这样会大大提高效率
首先要明白什么是事件流。事件流大致分为3个阶段:事件捕获阶段、处于目标阶段、事件冒泡阶段。ie8及其以下没有事件捕获阶段,只有后面两个阶段
事件捕获:事件从目标从上往下进行传播,从外往内传播。
事件冒泡:事件从目标从下往上进行传播,从内往外传播。
二者刚好相反,这样说太抽象了,下面的图片应该能直观的体现
接下来是最基本的,添加事件和删除事件
而最普通的方法如下:
var mydiv = document.getElementById("myDiv"); 添加事件: mydiv.onclick = function(){ alert("hello world!"); } 删除事件: mydiv.onclick = null;
下面是比较高端的用法:
addEventListener() 和 removeEventListener()
这是比较高端的用法,都需要接收3个参数,ie8及其以下不支持这种方式
第一个参数是事件的类型,第二个参数是对应的handler,第三个判断是否在冒泡阶段处理
为true,表示在捕获阶段处理, false表示在冒泡阶段处理事件
IE不支持在捕获阶段处理事件,为了兼容性考虑,通常选择在冒泡阶段处理事件
法一: mydiv.addEventListener('click',function(){ alert("hello world!"); }, false); 法二: mydiv.addEventListener('click', handler, false); function handler(){ alert("hello world!"); } 删除事件: mydiv.removeEventListener('click', handler, false);
只是ie8及其以下不支持这种方式,不过同时提供了另一种方式
attachEvent()和detachEvent()
mydiv.attachEvent('onclick',function(){ alert("hello world!"); }); mydiv.attachEvent('onclick', handler); function handler(){ alert("hello world!"); } 删除事件: mydiv.detachEvent('onclick', handler);
既然这里存在浏览器的兼容性问题,我们为什么不用一个方法将它们的差异封装起来,方便用户使用呢?
var EventUtil = { addEvent: function(element, eventType, handler){ if(element.addEventListener){//标准浏览器 element.addEventListener(eventType, handler, false); }else{ element.attachEvent('on' + eventType, handler); } }, removeEvent: function(element, eventType, handler){ if(element.removeEventListener){//标准浏览器 element.removeEventListener(eventType, handler, false); }else{ element.detachEvent('on' + eventType, handler); } } };我们使用它的时候,这样操作就可以了:
function handler(){ alert("hello world!"); } function over(){ alert("over!!!"); } function out(){ alert("out!!!"); } EventUtil.addEvent(mydiv, 'click', handler); EventUtil.addEvent(mydiv, 'mouseover', over); EventUtil.addEvent(mydiv, 'mouseout', out);如上面所示,大家有没有发现一个蛋疼的地方,如果我要对它添加(或删除)好几个事件,这样写起来会不会太麻烦了。我们是否能够简化它的写法呢?
那就换一种封装的方式:
var EventUtil = { addEvent: function(element, eventType, handler){ var event_arr = eventType.split(' '); if(event_arr.length != handler.length){ return; } for(var i = 0, len = event_arr.length; i<len; i++){ if(element.addEventListener){//标准浏览器 element.addEventListener(event_arr[i], handler[i], false); }else{ element.attachEvent('on' + event_arr[i], handler[i]); } } }, removeEvent: function(element, eventType, handler){ var event_arr = eventType.split(' '); if(event_arr.length != handler.length){ return; } for(var i = 0, len = event_arr.length; i<len; i++){ if(element.removeEventListener){//标准浏览器 element.removeEventListener(event_arr[i], handler[i], false); }else{ element.detachEvent('on' + event_arr[i], handler[i]); } } } };这样的话就可以这样方便的使用它了:
var mydiv = document.getElementById("myDiv"); function handler(){ alert("hello world!"); } function over(){ alert("over!!!"); } function out(){ alert("out!!!"); } EventUtil.addEvent(mydiv, 'click mouseover mouseout', [handler, over, out]);
下面来看一下event 对象
标准浏览器中:
target 指向鼠标操作的元素;currentTarget 指向添加事件的元素,也就是this
这里有两个例子,大家可以亲手测试一下,点击的区域不同,产生的结果不一样
var mydiv = document.getElementById("myDiv"); mydiv.onclick = function(event){ console.log(event.target === this); console.log(event.currentTarget === this); console.log(event.target === event.currentTarget); } document.body.onclick = function(event){ console.log(event.target === this); console.log(event.currentTarget === this); console.log(event.target === event.currentTarget); console.log(event.target === mydiv); }
下面针对事件冒泡举个例子:
var mydiv = document.getElementById("myDiv"); mydiv.onclick = function(event){ console.log('div clicked!'); } document.body.onclick = function(event){ console.log('body clicked!'); } document.getElementsByTagName('html')[0].onclick = function(event){ console.log('html clicked!'); }结果如下:
从这里也可以体会出事件冒泡的机理
阻止默认行为
标准浏览器是preventDefault(),IE是returnValue = false
同时这里要注意,IE和标准浏览器获取event的方式不一样
var link = document.getElementById('myLink'); 标准浏览器: link.onclick = function(event) { event.preventDefault(); } IE浏览器: link.onclick = function(event) { var evt = event || window.event; evt.preventDefault(); evt.returnValue = false; }
阻止冒泡
标准浏览器是stopPropagation(),IE是cancelBubble = true
标准浏览器阻止冒泡: var mydiv = document.getElementById('myDiv'); mydiv.onclick = function(event) { console.log('div clicked'); event.stopPropagation();//用来阻止冒泡 } document.body.onclick = function(event){ console.log('body clicked'); } IE浏览器阻止冒泡: var mydiv = document.getElementById('myDiv'); mydiv.onclick = function(event) { var evt = event || window.event; console.log('div clicked'); evt.cancelBubble = true;//用来阻止冒泡 } document.body.onclick = function(event){ console.log('body clicked'); }
1.IE和标准浏览器在event的获取上有差异
2.IE中没有标准浏览器中的target属性,但是有srcElement属性作为替代
3.IE中阻止默认行为会用到returnValue这个属性,false则取消默认行为。标准浏览器用preventDefault()
4.IE中取消事件冒泡会用到cancelBubble这个属性,为true会取消冒泡。标准浏览器用stopPropagation()
既然IE与标准浏览器在这么多地方存在差异,我们何不将之封装起来,让用户体会不到差异不是很好吗?
var EventUtil = { addEvent: function(element, eventType, handler){ var event_arr = eventType.split(' '); if(event_arr.length != handler.length){ return; } for(var i = 0, len = event_arr.length; i<len; i++){ if(element.addEventListener){//标准浏览器 element.addEventListener(event_arr[i], handler[i], false); }else{ element.attachEvent('on' + event_arr[i], handler[i]); } } }, removeEvent: function(element, eventType, handler){ var event_arr = eventType.split(' '); if(event_arr.length != handler.length){ return; } for(var i = 0, len = event_arr.length; i<len; i++){ if(element.removeEventListener){//标准浏览器 element.removeEventListener(event_arr[i], handler[i], false); }else{ element.detachEvent('on' + event_arr[i], handler[i]); } } }, getEvent: function(event){ return event || window.event; }, getTarget: function(event){ return this.getEvent(event).target || this.getEvent(event).srcElement; }, //阻止默认行为 preventDefault: function(event){ var evt = this.getEvent(event); if(evt.preventDefault){//标准浏览器 evt.preventDefault(); }else{ evt.returnValue = false; } }, //阻止事件冒泡 stopPropagation: function(event){ var evt = this.getEvent(event); if(evt.stopPropagation){//标准浏览器 evt.stopPropagation(); }else{ evt.cancelBubble = true; } } };
最后简单来说说事件代理(event delegation)
通过事件代理,可以把事件处理器添加到一个父级元素上,等待一个事件从它的子级元
素里冒泡上来,并且可以得知这个事件是从哪个元素开始的。这样就避免了把事件处理器
添加到多个子级元素上,提高了性能。
比如我们有一张数据量很大的html表格,现在有一个需求,用户通过鼠标能够对每一个单元格中的数据进行更改。
如果针对很一个单元格都添加一个事件将产生很大的性能问题,甚至是浏览器崩溃。如果在这里使用事件代理,我
们只需要把事件添加到table元素上面,并且判断出是哪个单元格被操作了,然后进行相应的处理,这样会大大提高效率
相关文章推荐
- js中事件委托详解
- js动态绑定事件
- 原生JS绑定滑轮滚动事件兼容常见浏览器
- 精通JavaScript开发课时20(JS事件基础)学习笔记
- js按回车事件提交
- JS来推断文本框内容改变事件
- Node.js中的事件驱动编程详解
- js调用.net后台事件,和后台调用前台等方法总结
- js对键盘输入事件绑定到特定按钮
- js 跨浏览器实现事件
- JS常用事件
- js之DOM和事件
- js笔记--事件
- JS 事件相关属性
- 原生JS里的onbeforeunload与onunload事件
- js学习笔记之事件处理模型
- js中事件重叠处理
- js中的DOM事件,不能说最全,只能说够用
- JS中取消事件的两种方式
- js实现touch移动触屏滑动事件