你所在位置:首页Javascript开发 → Javascript事件总结

Javascript事件总结

发布时间:2019-02-10

 

一、事件冒泡

1.1 事件的不同阶段

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

 

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

\

 

 

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

 

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"

 

 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

 

<html xmlns="http://www.w3.org/1999/xhtml" lang="zh" xml:lang="zh">

 

<head>

 

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />

 

<meta name="developer" content="Realazy" />

 

<title>Bubble in JavaScript DOM</title>

 

<style type="text/css" media="screen">

 

 p * {display:block; margin:4px; padding:4px; border:1px solid white;}

 

 textarea {width:20em; height:2em;}

 

</style>

 

<script type="text/javascript">

 

    //<![CDATA[

 

    function init(){

 

  var log = document.getElementsByTagName('textarea')[0];

 

  var all = document.getElementsByTagName('p')[0].getElementsByTagName('*');

 

  for (var i = 0, n = all.length; i < n; ++i){

 

   all[i].onmouver = function(e){

alert('鼠标现在进入的是:' + this.nodeName);

    this.style.border = '1px solid red';

 

 

 

    log.value = '鼠标现在进入的是:' + this.nodeName;

 

   };

 

   all[i].onmouseout = function(e){

alert('鼠标现在移出的是:' + this.nodeName);

    this.style.border = '1px solid white';

 

   };

 

  }

 

 

 

  var all2 = document.getElementsByTagName('p')[1].getElementsByTagName('*');

 

  for (var i = 0, n = all2.length; i < n; ++i){

 

   all2[i].onmouseover = function(e){

 

    this.style.border = '1px solid red';

 

 

 

    if (e) //停止事件冒泡

 

     e.stopPropagation();

 

    else

 

     window.event.cancelBubble = true;

 

   

 

    log.value = '鼠标现在进入的是:' + this.nodeName;

 

   };

 

   all2[i].onmouseout = function(e){

 

    this.style.border = '1px solid white';

 

   };

 

  }

 

 }

 

 window.onload = init;

 

    //]]>

 

</script>

 

</head>

 

<body>

 

<h1>Bubble in JavaScript DOM</h1>

 

<p>DOM树的结构是:</p>

 

<pre><code>

 

UL

 

  - LI

 

     - A

 

   - SPAN

 

</code></pre>

 

<p>

 

 <ul>

 

  <li><a href="#"><span>Bubbllllllllllllllle</span></a></li>

 

  <li><a href="#"><span>Bubbllllllllllllllle</span></a></li>

 

 </ul>

 

</p>

 

<textarea></textarea>

 

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

 

<p>

 

 <ul>

 

  <li><a href="#"><span>Bubbllllllllllllllle</span></a></li>

 

  <li><a href="#"><span>Bubbllllllllllllllle</span></a></li>

 

 </ul>

 

</p>

 

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

 

</body>

 

</html>

 

 

1.2 取消事件冒泡

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

 

1 function stopBubble(e) {2     if (e && e.stopPropagation) {3         e.stopPropagation(); //因为传入了事件对象e,并且支持W3C标准的stopPropagation()4     } else {5         window.event.cancelBubble = true; //For IE6     }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 action</a>  

 

《Pro Javascript Techniques》[美John Resig]一书中提到95%的情况中防止默认行为都有效,但是偶尔也会失效,因为该行为是由浏览器决定的,尤其是在谋居蛑蟹乐骨没骱蚷frame内的行为。除此之外,都应该无大碍。这是一本学习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标准浏览器则作为一个参数传进处理函数。

e

 

 

 

 

三、 事件绑定

各榔魉淙恢С值姆绞蕉疾惶谎窍啾然炻业a href="/kf/qianduan/css/" target="_blank" class="keylink">CSS,事件绑定还是有章可循的。IE有自己的实现方式,并且各版本统一,其他现代浏览器都按照W3C标准来实现。

 

3.1 传统Dom绑定

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

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

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

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

 

<a onclick="handle(event)" href="#">link</a>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 detection2 it does not use the addeventListener/attachEvent methods3 it keeps the correct scope (the this keyword)4 it passes the event object correctly5 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
上一篇:AJAX跨域请求json数据
下一篇:JavaScript中setAttribute用法