这是第一篇技术性博客。

因为最近做的web版前端求职简历算是告一段落了(点此看简历)。(稍微记录下吧:自从确定简历的简笔画风格后(因为刚开始设想的蓝天白云大树啥的不仅图片特难找而且做着做着就觉得有点俗了,简笔画这种黑白风格对PS技术要求就很低了),大概花了写这篇博客前的4、5天做好的(额,上班时间也在做,因为最近公司不忙))总之就是在做简历的过程中感觉对js事件了解多了一点,所以先记下来,以后争取能再完善。

  • 避免重复注册事件

这是我曾经在QQ群里求助的一个问题,感觉看过的书里也没有特意提到。具体来说就是一个元素相同的事件处理程序注册多次的话,每次执行时会把以前累计注册的事件都执行。这个问题在以下情况最常见:在元素aa的事件里创造了元素bb并给它添加了事件,如此一来每次a相应事件发生时都会给bb添加事件。

<!DOCTYPE html>
<html>
<style type="text/css">
#aa{background-color:lightgreen;}
#bb{background-color:pink;}
</style>
<body>
<p id="aa" >aa</p>
<p id="bb" >bb</p>

</body>
<script src="http://code.jquery.com/jquery-1.10.2.min.js" type="text/javascript"> </script>
<script type="text/javascript"> $(function(){
var i=0;
$('#aa').click(function(){
i++;
$('#bb').click(function(){
alert(i);
})
})
}) </script> </html>

运行代码

如#aa和#bb为兄弟节点:

$(function(){ var i=0;
$('#aa').click(function(){
i++;
$('#bb').click(function(){
alert(i);
})
})
})

如上,则第一次click #aa再click #bb时,  弹出1;

    第二次click #aa再click #bb时,连续弹出2、2;

    第三次click #aa再click #bb时,连续弹出3、3、3.

解决办法:先删除事件再添加,unbind以后再bind。

  • 重要的事件对象

我们知道在触发DOM上的某个事件时,会产生一个事件对象event,这个对象中包含着所有与事件有关的信息,包括导致事件的元素、事件类型等。其中的常用有:

1. event.type(被触发的事件的类型,如“click”);

2.event.eventPhase(调用事件处理程序的阶段:1表示捕获阶段,2表示"处于目标",3表示冒泡阶段)

3.event.target和event.currentTarget

4.event.stopPropagation()

这就涉及到事件流了,"DOM2级事件“规定的事件流包括三个阶段:事件捕获阶段、处于目标阶段和事件冒泡阶段。捕获阶段从document往下到目标节点的父元素就停止,然后是处于目标阶段,事件发生,在事件处理中也看成冒泡阶段的一部分,在冒泡阶段可以对事件作出响应。在事件处理程序内部,this始终等于event.currentTarget,表示注册事件的对象,而由于事件流导致冒泡阶段也会触发事件,而 event.target就表示实际的事件目标。(2013-8-21添加:并不是只在冒泡阶段响应,由于Netscape和IE的事件发生顺序不同,W3C综合了二者,可以选择是在捕获阶段还是冒泡阶段绑定事件处理函数,这是通过addEventListener()方法实现的,如果这个函数的最后一个参数是true,则在捕获阶段绑定函数,反之false,在冒泡阶段绑定函数。

"DOM2级事件“中添加事件处理程序:

var btn=document.getElementById('myBtn');

btn.addEventListener("click",function(){alert(this.id);},false);

大多数情况下,都是将事件处理程序添加到事件流的冒泡阶段,这样可以最大限度地兼容各种浏览器,不建议事件捕获阶段注册事件处理程序。W3C默认是绑定在冒泡阶段。)

比如一个元素包含一个子元素,为父元素添加事件:

    <div id='father'>
<p id='son' >aaaaa</p>
</div>
$('#father').click(function(event){
console.log(event.eventPhase);
     console.log("event.target:"+event.target+",event.currentTarget:"+event.currentTarget);
})

在不包含son的father区域click时为:

2  event.target:[object HTMLDivElement],event.currentTarget:[object HTMLDivElement];

在son上click时:

3 event.target:[object HTMLParagraphElement],event.currentTarget:[object HTMLDivElement]。
这也就解释了为什么event.target的含义,有动作发生时是从document向下捕获到event.target而不是event.currentTarget,然后向上冒泡到document,在捕获阶段不触发事件。可以通过event.stopPropagation()来取消冒泡(2013-8-21添加:IE中的是event.cancelBubble()来取消事件冒泡(jQuery已经统一用event.stopPropagation()来兼容了吧);DOM中的event.preventDefault()可以用来取消默认行为,如超链接的跳转,IE中的是要设置event.returnValue=false。)。
同样是上面的两个父子节点,可以看看下面这个例子的结果:
    $('#father').click(function(event){
alert ('father:'+event.eventPhase);
})
$('#son').click(function(event){
alert ('son:'+event.eventPhase);
})

在不包含son的father区域click时为:father:2

在son上click时:son:2 father:3

为son的click事件里添加event.stopPropagation()后就可以只son:2了。

(以上若有错恳请指正)

附注:如果想根据具体情况来执行某些语句,可以利用if(event.target == this)。或event.target.tagName.toUpperCase()来获取标签名(当然这办法对有多层子元素的很不好)。

判断一个对象是否为jQuery对象:if(obj instanceof jQuery),jQuery中比较两个对象是否为同一个对象:$('#son')==$('p')这样总是false,这样是在比较引用地址?还是jQuery没有这个办法?(

2013-8-21添加:在js中当比较两个使用值存储的数据时,若它们的值相同,等值比较的结果是true;如果比较两个使用引用存储的数据,当且仅当它们引用同一个值时,等值比较的结果才是true,比较的是引用(对应存储地址)。如

var a={x:1,y:2};

var b=a;

var c={x:1,y:2};

alert(a==b);//true

alert(a==c);//false

alert(a>=c);//不确定

)不过可以使用$(event.target).is($('p'))来判断。

  • 对含有子元素的节点对象的mouseenter、mouseleave和mouseover、mouseout

先来看一个例子:

$('#father').mouseover(function(event){
console.log(event.target+'eovered');
    $('#son').text(event.target+'overed').css('background','white');
}).mouseout(function(event){
console.log(event.target+'outed');
$('#son').text(event.target+'outed').css('background','red');
})

结果就是几十从father移入son、从son移除father,都会触发mouseover和mouseout啊。(页面从移出到移入的瞬间太快,效果不明显,从console.log里面看啊),这样是不是很烦哪?

如果你试试把mouseover和mouseout换成mouseenter和mouseleave,在IE8和最新版的grome和firefox里面一切就正常了啊,用IETester测试,连IE6都表现正常啊,IE9没有任何反应啊,就像没有加载js一样,IETester是不是坏了啊,我的IETester里的IE7一向都是打不开测试页面的,所以不知都IE7会怎么样啊,IETester很不好用啊,有木有推荐的其他工具啊?(欢迎补充更正具体的测试结果啊)

好吧,回正题,为什么会这样呢?

其实是就是因为DOM3级事件中定义的mouseenter、mouseleave都不冒泡,在光标移动到后代元素上不会触发。但DOM2级事件并没有定义这个事件,DOM3级事件将它纳入了规范,IE、Firefox9+和Opera支持这个事件。

就是这个样子啊。

但是非要用mouseover和mouseout的话,

W3C在mouseover和mouseout这两个触发的事件对象里添加了一个叫relatedTarget的属性,来表示与事件相关的DOM元素。event.mouseover中event.relatedTarget指向鼠标来自的元素,而mouseout中的relatedTarget指向的是鼠标去向的那个元素。据说在IE里对应的分别是event.fromElement和event.toElement(没测试过啦,jQuery都统一成event.relatedTarget)。

吐槽:原来写稍微技术一点的博客这么费时间啊, 从上午8点写到现在14:00,上午不过是打了2、3个小电话,填了些资料,中午都木有午休啊,原计划还要写一些UI事件的(UI事件是指那些不一定与用户操作有关的事件,如load、resize、scroll等,有时间再补充啊)。

总结:写技术博客最好还是放在晚上吧。

俺要工作了啊,看见有错的地方恳请指正啊,谢恩。

关于js中的事件的更多相关文章

  1. 怎么理解js中的事件委托

    怎么理解js中的事件委托 时间 2015-01-15 00:59:59  SegmentFault 原文  http://segmentfault.com/blog/sunchengli/119000 ...

  2. js中冒泡事件和捕获事件

    js中冒泡事件和捕获事件: 冒泡事件:冒泡事件是从里向外,即是从被绑定元素开始一直向外到达页面的所有祖先元素都会被触发,这 一过程被称为事件冒泡.这个事件从原始元素开始一直冒泡到DOM树的最上层 捕获 ...

  3. 看懂此文,不再困惑于 JS 中的事件设计

    看懂此文,不再困惑于 JS 中的事件设计 今天刚在关注的微信公众号看到的文章,关于JS事件的,写的很详细也很容易理解,相关的知识点都有总结到,看完就有种很舒畅的感觉,该串起来的知识点都串起来了.反正一 ...

  4. js中冒泡事件

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  5. DOM 以及JS中的事件

    [DOM树节点] DOM节点分为三大节点:元素节点,文本节点,属性节点. 文本节点,属性节点为元素节点的两个子节点通过getElment系列方法,可以去到元素节点 [查看节点] 1 document. ...

  6. 从零开始的JS生活(二)——BOM、DOM与JS中的事件

    上回书说道,JS中变量.运算符.分支结构.循环和嵌套循环等内容.本回就由本K给大伙唠唠JS中的BOM.DOM和事件. 一."花心大萝卜"--BOM 1.震惊,FFF团为何对BOM举 ...

  7. js中的事件,内置对象,正则表达式

    [JS中的事件分类] 1.鼠标事件: click/dbclick/mouseover/mouseout/mousemove/mousedown/mouseup 2.键盘事件: keydown: 键盘按 ...

  8. JS中的事件以及DOM 操作

    [DOM树节点] DOM节点分为三大节点:元素节点,文本节点,属性节点. 文本节点,属性节点为元素节点的两个子节点通过getElment系列方法,可以去到元素节点 [查看节点] 1 document. ...

  9. JS中的事件&对象

    一.JS中的事件 (一)JS中的事件分类 1.鼠标事件 click/dblclick/onmouseover/onmouseout 2.HTML事件 onload/onscroll/onsubmit/ ...

  10. JS学习五(js中的事件)

    [JS中的事件分类] 1.鼠标事件 click/bdlclick/onmouseover/onmouseout 2. HTML事件 onload/onscroll/onsubmit/onchange/ ...

随机推荐

  1. 第几天 AC 杭电

    第几天? Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submi ...

  2. xampp 命令行修改数据库密码

    进入xampp 下 ./mysql -u root -p password 进入mysql控制台 UPDATE mysql.user SET Password=PASSWORD('password') ...

  3. CA

    http://www.cmca.net/index.php?option=com_content&view=article&id=55&Itemid=16

  4. 【HDOJ】1332 LC-Display

    水题. #include <cstdio> #include <cstring> #include <cstdlib> #define MAXN 11 #defin ...

  5. [译] 新手和老手都将受益的JavaScript小技巧

    这篇文章会分享一些鲜为人知但却很强大的JavaScript技巧, 各个级别的JavaScript开发者都会从中受益.   1. 用数组的length属性清空数组   我们知道在JS中对象类型是按引用传 ...

  6. 通过 iTextSharp 实现PDF 审核盖章

    最近需要做一个PDF自动审核盖章的工作,其实就是读取PDF,然后再最后一页加入一个审核章印图片上去.看起来很简单,不过在开发过程中,还是遇到了一些问题,在这里记录一下. 主要遇到的问题是页面的旋转 和 ...

  7. Remote Desktop Connection Manager 多个远程管理

    http://www.microsoft.com/en-us/download/details.aspx?id=21101 Remote Desktop Connection Manager 多个远程 ...

  8. windows内核对象句柄

    内核对象用于管理进程.线程和文件等诸多种类的大量资源,每一个内核对象都只是一个句内存快,它由操作系统内核分配,并只能右操作系统内核访问.这个内存块是一个数据结构,其维护着与对象相关的信息,其中少数成员 ...

  9. Shell中变量的使用

    1.变量的声明 name="blacksonny" 注意://变量定义时不加$,变量与等号之间不能有空格 变量命名规则: 首个字符必须为字母(a-z,A-Z). 中间不能有空格,可 ...

  10. JS中的Math.ceil和Math.floor函数的用法

    Math.ceil(x) -- 返回大于等于数字参数的最小整数(取整函数),对数字进行上舍入 Math.floor(x)--返回小于等于数字参数的最大整数,对数字进行下舍入 例如: document. ...