Javascript事件总结javascript

事件冒泡

事件的不同阶段

取消事件冒泡

重载浏览器默认行为

常见事件对象

this

事件对象

事件绑定

传统dom绑定

w3c标准绑定

ie绑定

牛人们的解决方案

一、事件冒泡

1.1 事件的不同阶段

javascript事件在2个阶段执行:捕获与冒泡。

如下图的dom结构中如果指向锚点#1.1的链接被点击,则依次会触发document > body > ul > li > ul > li > a 的click处理函数。至此完成捕获阶段。当这阶段完成,开始冒泡阶段,如图中向上箭头的顺序。事件处理函数全部触发。有兴趣可以移步这里,可以看到动态的过程。

我们对上述代码稍加更改,假如alert,因为那个demo中的效果切换太快了,我们慢一点洗洗体会。【注:这里订阅的事件都是冒泡阶段的,也是最常用的,因为ie并不支持订阅捕获阶段的时间。比较特殊的还有opera,常常遇到有些特性向firefox系,偶尔会有个别特性像ie】。这篇文章也助于加深理解

bubble in javascript dom

dom树的结构是:

ul

- li

- a

- span

bubbllllllllllllllle

bubbllllllllllllllle

鼠标进入ul的任何一个子元素,如果不停止冒泡,我们从ul到span都定义了鼠标悬停(mouseover)事件,这个事件会上升了ul,从而从鼠标所进入的元素到ul元素都会有红色的边。

bubbllllllllllllllle

bubbllllllllllllllle

如果停止冒泡,事件不会上升,我们就可以获取精确的鼠标进入元素。

1.2 取消事件冒泡

其实1.1的代码中已经包含了取消事件冒泡的代码。这里我们专门提出来写,使其具有更好的兼容性与美观。

1 function stopbubble(e) {

2if (e && e.stoppropagation) {

3e.stoppropagation(); //因为传入了事件对象e,并且支持w3c标准的stoppropagation()

4} else {

5window.event.cancelbubble = true; //for ie

6}

7 }

【注】:我们不能简单的看到传入了事件对象就判断为非ie浏览器,因为有时候我们使用3.1的方式来绑定事件,此时极有可能也会传入一个window.event的引用。

1.3 重载浏览器默认行为

对于a标签等具有默认行为(如跳转到某url)的html元素,我们可能想要部分a表现的有特色些,点击某a就是不跳转,可以重载其默认行为。

function stopdetault(e) {

if (e&&e.preventdetault) {

e.preventdefault();

} else {

window.event.returnvalue = false;

}

return false;

}

使用方法:

document.getelementbyid("##").onclick = function (e) {

//do sth.

return stopdetault(e);

}

我们也常用下面的方式阻止默认行为,所以阻止事件处理函数本身return false也就可以理解了。

a href="javascript:alert('clicked');return false;">a link without redirect actiona>

《pro javascript techniques》[美 john resig]一书中提到95%的情况中防止默认行为都有效,但是偶尔也会失效,因为该行为是由浏览器决定的,尤其是在文本域中防止敲击和iframe内的行为。除此之外,都应该无大碍。这是一本学习javascript的好书。推荐。

二、 常见事件对象

2.1 this

this 关键字是javascript中提供对当前对象引用的变量。绑定事件时this通常指的是当前元素,但是也有例外!!初接触javascript觉得这个this有点变换莫测,难以捉摸。

如果你的感觉也是这样,可以看看下边的文章:

javascript this关键字使用分析

[图解] 你不知道的 javascript - “this”

通常在绑定事件时可以这样使用this

document.getelementbyid("input1").onclick = function(e){

this.style.color="red";

};

2.2 事件对象

通过对下面的代码调试我们可以看到,事件对象通常包含当前键码等事件相关信息。值得一提的是ie的实现把事件对象放在一个全局变量window.event变量中保存,而其他遵从w3c标准浏览器则作为一个参数传进处理函数。

三、 事件绑定

各浏览器虽然支持的方式都不太一样,但是相比混乱的css,事件绑定还是有章可循的。ie有自己的实现方式,并且各版本统一,其他现代浏览器都按照w3c标准来实现。

3.1 传统dom绑定

这种方式最简单,最有效。而且this关键词指向的是当前元素。但是缺点也不少,他们是:

1.只能绑定一次。假如我们引用的多个类库中都对window.onload事件进行绑定,则前边的绑定将会被后边的覆盖,并且常常难以察觉。

2.只支持订阅冒泡阶段事件。

3.事件参数只支持非ie,虽然事件对象参数仅支持非ie浏览器,但是我们可以使用下边这种方式解决。

a οnclick="handle(event)" href="#">linka>

3.2 w3c标准绑定

这个是最开心的方式了,除ie以外的现代浏览器都支持,我们可以直接使用每个dom元素的addeventlistener(eventname,handlefunc,trueorfalse),第一个参数为订阅的事件名称,如click(没有on),第二个参数为时间处理函数,第三个参数为是否订阅事件捕获阶段。

下面是使用addeventlistener的例子

document.getelementbyid("linka").addeventlistener('click', function (e) {

alert('i am clicked!');

return stopdetault(e);

}, false);

优点:

1.支持冒泡与捕获阶段。

2.在处理函数内部,this关键字引用当前元素。

3.可以为同一元素的同一时间绑定多个处理函数,不会覆盖。

缺点:

1.ie不支持

3.3 ie绑定

既然上边提到ie不支持addeventlistener,那么肯定要找个解决方案帮帮ie小兄弟,那就是attachevent,虽然有很多缺点,但也够用。

下面是attachevent的例子

document.attachevent("onload", function () {

alert("i am load");

});

优点:

1.当然这个优点是和第一种绑定方式相比的:),同一元素支持多次绑定。

缺点:

1.仅支持ie事件的冒泡阶段。

2.事件处理函数内部this关键字引用了window对象。要解决这个问题请继续往下看。

3.事件名前必须加on,当然这个只是叫法不同,也没什么大碍。

4.只支持ie啊,这个很痛啊。

四、 牛人们的解决方案

dean edwards的方案:addevent/removeevent库

这个方案比较特别。详细请移步这里

特点:

1 it performs no object detection

2 it does not use the addeventlistener/attachevent methods

3 it keeps the correct scope (the this keyword)

4 it passes the event object correctly

5 it is entirely cross-browser (it will probably work on ie4 and ns4)

6 and from what i can tell it does not leak memory

源码:

function handleevent(event) {

var returnvalue = true;

// grab the event object (ie uses a global event object)

event = event || fixevent(window.event);

// get a reference to the hash table of event handlers

var handlers = this.events[event.type];

// execute each event handler

for (var i in handlers) {

this.$$handleevent = handlers[i];

if (this.$$handleevent(event) === false) {

returnvalue = false;

}

}

return returnvalue;

};

function fixevent(event) {

// add w3c standard event methods

event.preventdefault = fixevent.preventdefault;

event.stoppropagation = fixevent.stoppropagation;

return event;

};

fixevent.preventdefault = function() {

this.returnvalue = false;

};

fixevent.stoppropagation = function() {

this.cancelbubble = true;

};

【注】:这个方案有一个致命的东西,千万不要这样做这样会覆盖之前绑定的处理函数

body οnlοad="alert('hi');">body>


======================================================
在最后,我邀请大家参加新浪APP,就是新浪免费送大家的一个空间,支持PHP+MySql,免费二级域名,免费域名绑定 这个是我邀请的地址,您通过这个链接注册即为我的好友,并获赠云豆500个,价值5元哦!短网址是http://t.cn/SXOiLh我创建的小站每天访客已经达到2000+了,每天挂广告赚50+元哦,呵呵,饭钱不愁了,\(^o^)/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值