js的事件的三个阶段,事件委托的原理
DOM2级事件规定的事件流的三个阶段:捕获,目标,冒泡(IE8以及更早版本不支持DOM事件流);
var btn = document.getElementById_x_x_x("btn"); btn.onclick = function(){ alert(this.id); // 弹出btn }
单击元素btn后,通过this.id取得元素的属性id,还可以通过this访问元素的任何属性和方法,以这种方式添加的事情处理程序在事件流的冒泡阶段处理。
也可以删除通过DOM0级方法指定的事件处理程序,只要将事件处理程序的属性值设置为null即可。
btn.onclick = null; // 删除事件处理程序;
DOM2级事件处理程序
事件是在冒泡阶段被触发,与DOM0级方法一样,这里添加的事件处理程序也是在其依副的元素作用域中运行,使用DOM2级添加事件处理程序的好处是可以添加多个事件处理程序,如下代码:
var btn = document.getElementById_x_x_x("btn"); btn.addEventListener('click',function(e){ alert(this.id); },false); btn.addEventListener('click',function(e){ alert("我是来测试的"); },false);
上面的代码被弹出2次对话框,而在DOM0级是不可以的;它永远是执行最后一次的。
参考:http://www.admin10000.com/document/6293.html
IE事件处理的程序
btn.attachEvent('onclick',handler); function handler(e){ alert(this); // window }
注意:attachEvent的事件名称是onclick,而addEventListener的事件名称是click,且IE中使用的attachEvent()与使用DOM0级方法的的主要区别在于事件处理程序的作用域,在使用dom0级情况下,事件处理程序在其所属元素的作用域内运行,在使用attachEvent()方法的情况下,事件处理程序在全局作用域下运行,其中的this等于window。
理解标准浏览器下的事件对象与IE下的事件对象
标准浏览器下的事件对象是event,比如btn点击后;如下代码:
var btn = document.getElementById_x_x_x("btn"); btn.onclick = function(){ console.log(event); //标准浏览器下打印事件对象 console.log(event.type);//'click' } btn.onclick = function(){ // IE下打印的事件对象window.event console.log(window.event); console.log(window.event.type); // 'click' }
上面的写法是在DOM0级上注册事件,如果我们在Dom2级上注册事件的话,那么就会有一个事件对象event作为参数传入事件到函数中,如下:
var btn = document.getElementById_x_x_x("btn"); EventUtil.addHandler(btn,'click',function(e){ console.log(e); });
理解特定事件的默认行为事件
alink.onclick = function(e){ console.log(e) e.preventDefault(); }
IE下
alink.onclick = function(){ console.log(window.event) window.event.returnValue = false; }
标准浏览器下与IE下的事件目标的区别
console.log(event.target); // 打印事件目标元素
console.log(window.event.srcElement);
理解标准浏览器与IE下阻止事件传播的区别
在标准浏览器下我们可以使用stopPropagation()方法来停止事件在DOM层次中的传播,即取消事件中的冒泡或者捕获。从而避免触发注册在document.body上面的事件处理程序
标准浏览器e.stopPropagation()
IE:window.event.cancelBubble = true
跨浏览器的事件对象
var EventUtil = {
addHandler : function(element, type, handler) {
if (element.addEventListener) {
element.addEventListener(type, handler, false);
} else if (element.attachEvent) {
element.attachEvent("on" + type, handler);
} else {
element["on" + type] = handler;
}
},
removeHandler : function(element, type, handler) {
if (element.removeEventListener) {
element.removeEventListener(type, handler, false);
} else if (element.detachEvent) {
element.detachEvent("on" + type, handler);
} else {
element["on" + type] = null;
}
},
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.stopPropagation) {
event.stopPropagation();
} else {
event.cancelBubble = true;
}
}
};
理解客户区坐标位置
含义是:鼠标指针在可视区中的水平clientX和垂直clientY坐标;
如下图所示:
理解页面坐标位置pageX和pageY:
pageX与pageY是指页面坐标的位置,与clientX和clientY的区别是:它包含页面滚动条的位置,如下图所示:
但是IE8及更早的版本不支持pageX与pageY
EventUtil.addHandler(btn,'click',function(e){ e = EventUtil.getEvent(e); var pageX = e.pageX, pageY = e.pageY; if(!pageX) { pageX = e.clientX + (document.body.scrollLeft || document.documentElement.scrollLeft); } if(!pageY) { pageY = e.clientY + (document.body.scrollTop || document.documentElement.scrollTop); } console.log("页面X轴坐标为:"+pageX + " "+ "页面Y轴坐标为:"+pageY); });
理解屏幕坐标的位置
屏幕横坐标screenX和垂直坐标screenY属性是相对于整个屏幕的。如下图所示:
Javascript事件委托的原理
原理:使用事件委托技术能让你避免对特定的每个节点添加事件监听器;相反,事件监听器是被添加到它们的父元素上,利用冒泡的原理,把事件加到父级上,触发执行效果。
eg:
<</span>ul id="parent-list">
<</span>li id="post-1">Item 1</</span>li>
<</span>li id="post-2">Item 2</</span>li>
<</span>li id="post-3">Item 3</</span>li>
<</span>li id="post-4">Item 4</</span>li>
<</span>li id="post-5">Item 5</</span>li>
<</span>li id="post-6">Item 6</</span>li>
</</span>ul>
function getEventTarget(e) {
e = e || window.event;
return e.target || e.srcElement;
}
// 获取父节点,并为它添加一个click事件
document.getElementById_x("parent-list").addEventListener("click",function(e) {
// 检查事件源e.targe是否为Li
var target = getEventTarget(e);
if(target && target .nodeName.toUpperCase == "LI") {
// 真正的处理过程在这里
console.log("List item ",e.target.id.replace("post-")," was clicked!");
}
});
优点
通过上面的介绍,大家应该能够体会到使用事件委托对于web应用程序带来的几个优点:
1.可以大量节省内存占用,减少事件注册。
2.可以方便地动态添加和修改元素,不需要因为元素的改动而修改事件绑定。
3.JavaScript和DOM节点之间的关联变少了,这样也就减少了因循环引用而带来的内存泄漏发生的概率。
缺点:
不是所有的事件都能冒泡的。blur、focus、load和unload不能像其它事件一样冒泡。事实上blur和focus可以用事件捕获而非事件冒泡的方法获得(在IE之外的其它浏览器中)。
在管理鼠标事件的时候有些需要注意的地方。如果你的代码处理mousemove事件的话你遇上性能瓶颈的风险可就大了,因为mousemove事件触发非常频繁。而mouseout则因为其怪异的表现而变得很难用事件代理来管理。
参考:http://www.cnblogs.com/silence516/archive/2009/09/03/delegateEvent.html
js的事件的三个阶段,事件委托的原理的更多相关文章
- js:捕获冒泡和事件委托
一.事件流(捕获,冒泡) 事件流:指从页面中接收事件的顺序,有冒泡流和捕获流. 当页面中发生某种事件(比如鼠标点击,鼠标滑过等)时,毫无疑问子元素和父元素都会接收到该事件,可具体顺序是怎样的呢?冒 ...
- JS之捕获冒泡和事件委托
一.事件流(捕获,冒泡) 事件流:指从页面中接收事件的顺序,有冒泡流和捕获流. 当页面中发生某种事件(比如鼠标点击,鼠标滑过等)时,毫无疑问子元素和父元素都会接收到该事件,可具体顺序是怎样的呢?冒 ...
- js之捕捉冒泡和事件委托
以下为转载内容 一.事件流(捕获,冒泡) 事件流:指从页面中接收事件的顺序,有冒泡流和捕获流. 当页面中发生某种事件(比如鼠标点击,鼠标滑过等)时,毫无疑问子元素和父元素都会接收到该事件,可具体 ...
- JS事件对象与事件委托
事件对象 包含事件相关的信息,如鼠标.时间.触发的DOM对象等 js默认将事件对象封装好,并自动的以参数的形式,传递给事件处理函数的第1个参数,如下: document.getElementsByTa ...
- js事件捕获,事件冒泡,事件委托以及DOM事件流
一:DOM事件流: 事件流是从页面接收事件的顺序,DOM2级事件规定事件流包括三个阶段: ①事件捕获阶段:用意在于事件达到目标之前捕获它,在事件捕获阶段事件流模型:document→html→body ...
- js事件冒泡和事件委托
js事件冒泡 js所谓的事件冒泡就是子级元素的某个事件被触发,它的上级元素的该事件也被递归执行 html: <ul class="clearfix" data-type=&q ...
- JS中的事件绑定,事件捕获,事件冒泡以及事件委托,兼容IE
转载请注明出处:http://www.cnblogs.com/zhangmingze/p/4864367.html ● 事件分为三个阶段: 事件捕获 --> 事件目标 --> ...
- js委托事件和代理事件
转载出处:https://www.cnblogs.com/liugang-vip/p/5616484.html js中的事件委托或是事件代理详解 起因: 1.这是前端面试的经典题型,要去找工作的小伙伴 ...
- js进阶---12-12、jquery事件委托怎么使用
js进阶---12-12.jquery事件委托怎么使用 一.总结 一句话总结:通过on方法(事件委托),给要绑定事件的元素的祖先绑定事件,从而达到效果. 1.事件委托是什么? 通过事件冒泡,让子元素绑 ...
随机推荐
- OpenCV-Python Tutorials目录
版本 3.4.6 1 Introduction to OpenCV OpenCV介绍Learn how to setup OpenCV-Python on your computer! 2 Gui F ...
- 牛客CSP-S提高组赛前集训营1
牛客CSP-S提高组赛前集训营1 比赛链接 官方题解 before:T1观察+结论题,T2树形Dp,可以换根或up&down,T3正解妙,转化为图上问题.题目质量不错,但数据太水了~. A-仓 ...
- 校园商铺-2项目设计和框架搭建-8升级mysql驱动相关的配置以支持mysql8
1.如何升级驱动 1.1步骤: a 确保当前程序能正常访问数据库 b 更新mysql驱动重新运行程序进行校验 maven依赖https://mvnrepository.com/artifact/mys ...
- bsgs+求数列通项——bzoj3122(进阶指南模板该进)
/* 已知递推数列 F[i]=a*F[i-1]+b (%c) 解方程F[x]=t an+1 = b*an + c an+1 + c/(b-1) = b(an + c/(b-1)) an+1 + c/( ...
- LUOGU P3161 [CQOI2012]模拟工厂 (贪心)
传送门 解题思路 贪心,首先因为\(n\)比较小,可以\(2^n\)枚举子集.然后判断的时候就每次看后面的如果用最大生产力生产能不能达成目标,解一个二次函数. 代码 #include<iostr ...
- JavaScript中纯JS写21点游戏
// 21点游戏 分为人机对战和人人对战 // 玩家每次抽一张牌 牌的点数为1-10点随机数 谁更接近21点谁就获胜 let readline = require("readline-syn ...
- 将maven项目打成war包
//修改成war包 <packaging>war</packaging> //plugins中添加新的配置 <build> <plugins> < ...
- Java代码启动/关闭进程
ProcessBuilder builder = new ProcessBuilder(命令,参数,参数...); Process process = builder.start(); br = ne ...
- 通过java进行电脑屏幕截图
package image; import java.awt.Desktop; import java.awt.Dimension; import java.awt.Rectangle; import ...
- ERROR 1839 (HY000): @@GLOBAL.GTID_PURGED can only be set when @@GLOBAL.GTID_MODE = ON
从cdb上dump一个库结构,准备与本地结构做对比(可以直接compare,但速度贼慢).使用dump脚本在本地创建的时候报错 -- 导出指定库的结构 shell> mysqldump -hxx ...