zoukankan      html  css  js  c++  java
  • javascript事件

    JavaScript与HTML的交互是通过事件实现的,事件就是文档或浏览器窗口中发生的一些特定的交互瞬间,是用户或浏览器自身执行的某种动作,例如click,mouseover等都是事件名。

    (一)事件流

    事件流描述的是从页面中接收事件的顺序。

    1)事件冒泡

    IE中的事件流叫做事件冒泡,即事件开始是由最具体的元素(文档中嵌套层次最深的那个节点)接收,然后逐级向上传播到较为不具体的节点(文档)。如下例1.1所示:

    1. <html>  
    2. <head>  
    3.     <title> Event Bubbling Example </title>  
    4. </head>  
    5. <body>  
    6.     <div id="myDiv">Click Me</div>  
    7. </body>  
    8. </html>  
    <html>
    <head>
    	<title> Event Bubbling Example </title>
    </head>
    <body>
    	<div id="myDiv">Click Me</div>
    </body>
    </html>


    若单击<div>元素,那么click事件会按照如下顺序传播:

    a)<div>

    b)<body>

    c)<html>

    d)<document>

    click事件会在<div>元素上发生,然后沿着DOM树向上传播,在每一级节点上都发生,直到传播到document对象。如下图所示:

    所有现代浏览器都支持事件冒泡,但有区别。IE5.5及更早的版本的事件冒泡跳过<html>元素,直接从<body>到<document >,Firefox、Chrome和Safari则将事件一直冒泡到window对象。下面为一个事件冒泡实例,使用jQuery实现:

    1. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">  
    2. <html xmlns="http://www.w3.org/1999/xhtml">  
    3. <head>  
    4. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />  
    5. <title>Event Bubbling Example</title>  
    6. <style type="text/css">  
    7. *{margin:0;padding:0;}    
    8. body { font-size: 13px; line-height: 130%; padding: 60px; }  
    9. #content {  220px; border: 1px solid #0050D0;background: #96E555 }  
    10. span {  200px; margin: 10px; background: #666666; cursor: pointer;color:white;display:block;}  
    11. p {200px;background:#888;color:white;height:16px;}  
    12. </style>  
    13. <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.0/jquery.min.js" type="text/javascript"></script>  
    14. <script type="text/javascript">  
    15. $(function(){  
    16.     // 为span元素绑定click事件  
    17.     $('span').bind("click",function(){  
    18.         var txt = $('#msg').html() + "<p>内层span元素被点击.<p/>";  
    19.         $('#msg').html(txt);  
    20.     });  
    21.     // 为div元素绑定click事件  
    22.     $('#content').bind("click",function(){  
    23.         var txt = $('#msg').html() + "<p>外层div元素被点击.<p/>";  
    24.         $('#msg').html(txt);  
    25.     });  
    26.     // 为body元素绑定click事件  
    27.     $("body").bind("click",function(){  
    28.         var txt = $('#msg').html() + "<p>body元素被点击.<p/>";  
    29.         $('#msg').html(txt);  
    30.     });  
    31. })  
    32. </script>  
    33. </head>  
    34. <body>  
    35. <div id="content">  
    36.     外层div元素  
    37.     <span>内层span元素</span>  
    38.     外层div元素  
    39. </div>  
    40.   
    41. <div id="msg"></div>  
    42. </body>  
    43. </html>  
    <!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">
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>Event Bubbling Example</title>
    <style type="text/css">
    *{margin:0;padding:0;}	
    body { font-size: 13px; line-height: 130%; padding: 60px; }
    #content {  220px; border: 1px solid #0050D0;background: #96E555 }
    span {  200px; margin: 10px; background: #666666; cursor: pointer;color:white;display:block;}
    p {200px;background:#888;color:white;height:16px;}
    </style>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.0/jquery.min.js" type="text/javascript"></script>
    <script type="text/javascript">
    $(function(){
    	// 为span元素绑定click事件
    	$('span').bind("click",function(){
    		var txt = $('#msg').html() + "<p>内层span元素被点击.<p/>";
    		$('#msg').html(txt);
    	});
    	// 为div元素绑定click事件
    	$('#content').bind("click",function(){
    	    var txt = $('#msg').html() + "<p>外层div元素被点击.<p/>";
    		$('#msg').html(txt);
    	});
    	// 为body元素绑定click事件
    	$("body").bind("click",function(){
    		var txt = $('#msg').html() + "<p>body元素被点击.<p/>";
    		$('#msg').html(txt);
    	});
    })
    </script>
    </head>
    <body>
    <div id="content">
    	外层div元素
    	<span>内层span元素</span>
    	外层div元素
    </div>
    
    <div id="msg"></div>
    </body>
    </html>

    单击最内层<span>元素时,显示结果如下:

    2)事件捕获

    事件捕获的思想是不太具体的节点应该更早接收事件,而最具体的节点应该最后接收到事件。事件捕获的用意在于事件到达预定目标之前捕获它。在例1.1中,那么单击<div>元素会以下列顺序触发click事件:

    a)document

    b)<html>

    c)<body>

    d)<div>

    事件捕获中,document对象首先接收到click事件,然后沿着DOM树依次向下,一直传播到事件的实际目标,即<div>元素。如下图所示:

    3)DOM事件流

    “DOM2级事件”规定了事件流的三个阶段:事件捕获阶段、处于目标阶段、事件冒泡阶段。例1.1中单击<div>元素会按照下图触发事件:

    在DOM事件流中,实际的目标(<div>元素)在捕获阶段不会接收事件。在捕获阶段,事件从document到<html>再到<body>后就停止了;下一个阶段是“处于目标”阶段,于是事件在<div>上发生,并在事件处理中被看成冒泡的一部分;然后是冒泡阶段,事件又传播回文档。

    除了IE不支持DOM事件流,其余四大主流浏览器都支持。

    (二)事件处理程序

    响应某个事件的函数就叫做事件处理程序,或称为事件侦听器。事件处理程序都是以"on"开头的。例如onclick、onload事件。

    下面介绍为事件指定处理程序的几种方法:

    1)HTML事件处理程序

    某个元素支持每种事件,都可以使用一个与相应事件处理程序同名的HTML特性表示。该特性的值是能够执行的JavaScript代码。如下例所示:

    1. <input type="button" value="Click Me" onclick="alert('Clicked')"/>  
    <input type="button" value="Click Me" onclick="alert('Clicked')"/>

    也可以使用下述方法,先定义事件处理程序执行的具体动作:

    1. <script type="text/javascript">     
    2.     function showMessage(){  
    3.         alert("hello world!");  
    4.     }  
    5. </script>  
    6. <input type="button" value="Click Me" onclick=" showMessage()" />  
    <script type="text/javascript">	
    	function showMessage(){
    		alert("hello world!");
    	}
    </script>
    <input type="button" value="Click Me" onclick=" showMessage()" />
    

    事件处理程序也可以被包含在独立的外部文件中,事件处理程序中的代码在执行时,有权利访问全局作用域中的任何代码。

    HTML事件处理程序缺点:

    a)时差问题。用户可能在HTML元素一出现就触发相应事件,而此时事件处理程序有可能还不具备执行条件。

    上例中若showMessage()函数在按钮的下方,页面的最底部定义时,若用户在解析showMessage()函数之前就单击按钮,就会引发错误。需将事件错误处理程序放在一个try-catch块中。

    1. <input type="button" value="Click Me" onclick="try{showMessage();} catch(ex){}"/>  
    <input type="button" value="Click Me" onclick="try{showMessage();} catch(ex){}"/>

    b)HTML与JS代码紧密耦合。

    2)DOM0级事件处理程序

    通过js指定事件处理程序的传统方法,就是将一个函数赋值给一个事件处理程序的属性。该方法比较简单,而且具有跨浏览器的优势。

    在使用js指定事件处理程序时,需要指定一个操作对象的引用。每个元素(包括window和document)都有自己的事件处理程序属性,属性通常全部小写,例如onclick。

    [javascript] view plain copy
     
    print?
    1. var btn=document.getElementById("myBtn");  
    2. btn.onclick=function(){  
    3.     alert("Clicked");  
    4. };  
    var btn=document.getElementById("myBtn");
    btn.onclick=function(){
        alert("Clicked");
    };

    该方法指定的事件处理程序被认为是元素的方法,在元素的作用域中运行的。

    [javascript] view plain copy
     
    print?
    1. var btn=document.getElementById("myBtn");  
    2. btn.onclick=function(){  
    3.     alert(this.id);  //"myBtn"  
    4. };  
    var btn=document.getElementById("myBtn");
    btn.onclick=function(){
        alert(this.id);  //"myBtn"
    };

    可以在任何事件处理程序中通过this访问元素的任何属性和方法。以这种方式添加的事件处理程序会在事件流的冒泡阶段被处理。

    也可以删除DOM0级方法中指定的事件处理程序。

    [javascript] view plain copy
     
    print?
    1. btn.onclick=null;  //删除事件处理程序  
    btn.onclick=null;  //删除事件处理程序

    HTML事件处理程序中。onclick属性就是一个包含着同名HTML特性中指定的代码的函数,也可设置相应的属性为null,删除这种指定的事件处理程序。

    3)DOM2级事件处理程序

    定义两种方法用于指定和删除事件处理程序的操作:addEventListener()和removeEventListener()。

    这两种方法介绍三个参数:要处理的事件名,作为事件处理程序的函数和一个布尔值。

    布尔值为true表示在捕获阶段调用事件处理程序,如果为false表示在冒泡阶段调用事件处理程序。如下例所示:

    a)addEventListener()

    [javascript] view plain copy
     
    print?
    1. var btn=document.getElementById("myBtn");  
    2. btn.addEventListener("click",function(){  
    3.     alert("this.id");  
    4. },false);  
    var btn=document.getElementById("myBtn");
    btn.addEventListener("click",function(){
    	alert("this.id");
    },false);

    该方法添加的事件处理程序也是在元素的作用域中运行的。

    使用此方法的好处是可以添加多个事件处理程序,如下例所示:

    [javascript] view plain copy
     
    print?
    1. var btn=document.getElementById("myBtn");  
    2. btn.addEventListener("click",function(){  
    3.     alert("this.id");  
    4. },false);  
    5. btn.addEventListener("click",function(){  
    6.     alert("Hello World!");  
    7. },false);  
    var btn=document.getElementById("myBtn");
    btn.addEventListener("click",function(){
    	alert("this.id");
    },false);
    btn.addEventListener("click",function(){
    	alert("Hello World!");
    },false);

    这两种事件处理程序会按照添加它们的顺序触发。
    b)removeEventListener()

    通过addEventListener()添加的事件处理程序只能通过removeEventListener()来删除,而且需要传入的参数与添加事件处理程序的参数相同

    1. var btn=document.getElementById("myBtn");  
    2. btn.addEventListener("click",function(){  
    3.     alert("this.id");  
    4. },false);  
    5. //省略其他的代码  
    6. btn.removeEventListener("click",function(){  //没有用!传入的是完全不同的函数  
    7.     alert("this.id");  
    8. },false);  
    var btn=document.getElementById("myBtn");
    btn.addEventListener("click",function(){
    	alert("this.id");
    },false);
    //省略其他的代码
    btn.removeEventListener("click",function(){  //没有用!传入的是完全不同的函数
    	alert("this.id");
    },false);

    可使用下例方法:

    [javascript] view plain copy
     
    print?
    1. var btn=document.getElementById("myBtn");  
    2. var handler=function(){  
    3.     alert("this.id");  
    4. };  
    5. btn.addEventListener("click",handler,false);  
    6.   
    7. //省略其他的代码  
    8. btn.removeEventListener("click",handler,false);  
    var btn=document.getElementById("myBtn");
    var handler=function(){
    	alert("this.id");
    };
    btn.addEventListener("click",handler,false);
    
    //省略其他的代码
    btn.removeEventListener("click",handler,false);

    大多数都是将事件处理程序添加到事件流中的冒泡阶段,可以更好的兼容更多的浏览器。

    4)IE事件处理程序

    IE中使用与DOM类似的两种方法:attachEvent()和detachEvent()。只接受相同的两个参数:事件处理程序名称和事件处理程序函数。IE只支持冒泡。

    a)attachEvent()

    [javascript] view plain copy
     
    print?
    1. var btn=document.getElementById("myBtn");  
    2. btn.attachEvent("onclick",function(){  //参数为onclick,与DOM中addEventListener中的参数不同  
    3.         alert("Clicked");  
    4. });  
    var btn=document.getElementById("myBtn");
    btn.attachEvent("onclick",function(){  //参数为onclick,与DOM中addEventListener中的参数不同
            alert("Clicked");
    });

    此方法中的事件处理程序会在全局作用域中运行,因此this等于window,如下例所示:

    [javascript] view plain copy
     
    print?
    1. var btn=document.getElementById("myBtn");  
    2. btn.attachEvent("onclick",function(){  
    3.     alert(this==window); //true  
    4. });  
    var btn=document.getElementById("myBtn");
    btn.attachEvent("onclick",function(){
    	alert(this==window); //true
    });

    attachEvent()也可以为一个元素添加多个事件处理程序。但添加的事件处理程序不是以添加的顺序执行,而是以相反的顺序被触发。

    b)detachEvent()

    两种方法的参数必须是相同的,意味着添加的匿名函数将不能被移除。可使用下述方法,将保存在变量handler中的函数作为事件处理程序:

    [javascript] view plain copy
     
    print?
    1. var btn=document.getElementById("myBtn");  
    2. var handler=function(){  
    3.     alert("Clicked");  
    4. };  
    5. btn.attachEvent("onclick",handler);  
    6. btn.detachEvent("onclick",handler);  
    var btn=document.getElementById("myBtn");
    var handler=function(){
    	alert("Clicked");
    };
    btn.attachEvent("onclick",handler);
    btn.detachEvent("onclick",handler);

    5)跨浏览器的事件处理程序

    创建方法addHandler()方法和removeHandler()方法,方法属于一个EventUtil对象,用于添加和移除事件处理成程序。如下所示:

    [javascript] view plain copy
     
    print?
    1. //跨浏览器的事件处理程序  
    2. var EventUtil={  
    3.     addHandler:function(element,type,handler){  
    4.         if(element.addEventListener){  //检测DOM2级方法  
    5.             element.addEventListener(type,handler,false);  
    6.         } else if(element.attachEvent){  //检测IE方法  
    7.             element.attachEvent("on"+type,handler);  
    8.         } else{  
    9.             element["on"+type]=handler;   //使用DOM0方法  
    10.         }  
    11.     },  
    12.     removeHandler:function(element,type,handler){  
    13.         if(element.removeEventListener){  //检测DOM2级方法  
    14.             element.removeEventListener(type,handler,false);  
    15.         } else if(element.detachEvent){  //检测IE方法  
    16.             element.detachEvent("on"+type,handler);  
    17.         } else{  
    18.             element["on"+type]=null;   //使用DOM0方法  
    19.         }  
    20.     }  
    21. };  
    //跨浏览器的事件处理程序
    var EventUtil={
    	addHandler:function(element,type,handler){
    		if(element.addEventListener){  //检测DOM2级方法
    			element.addEventListener(type,handler,false);
    		} else if(element.attachEvent){  //检测IE方法
    			element.attachEvent("on"+type,handler);
    		} else{
    			element["on"+type]=handler;   //使用DOM0方法
    		}
    	},
    	removeHandler:function(element,type,handler){
    		if(element.removeEventListener){  //检测DOM2级方法
    			element.removeEventListener(type,handler,false);
    		} else if(element.detachEvent){  //检测IE方法
    			element.detachEvent("on"+type,handler);
    		} else{
    			element["on"+type]=null;   //使用DOM0方法
    		}
    	}
    };

    可以像下面这样使用EventUtil对象:

    [javascript] view plain copy
     
    print?
    1. var btn=document.getElementById("myBtn");  
    2. var handler=function(){  
    3.     alert("Clicked");  
    4. };  
    5. EventUtil.addHandler(btn,"click",handler);  
    6. //省略其他代码  
    7. EventUtil.removeHandler(btn,"click",handler);  
    var btn=document.getElementById("myBtn");
    var handler=function(){
    	alert("Clicked");
    };
    EventUtil.addHandler(btn,"click",handler);
    //省略其他代码
    EventUtil.removeHandler(btn,"click",handler);

    该两种方法仅用来添加和移除事件处理程序,并没有考虑所有的浏览器问题,例如IE中作用域问题。

    未完待续(*^__^*)

    参考:《JavaScript高级程序设计(第二版)》

  • 相关阅读:
    pgspider sqlite mysql docker 镜像
    pgspider docker 镜像
    pgspider基于pg 的高性能数据可视化sql 集群引擎
    diesel rust orm 框架试用
    golang 条件编译
    Performance Profiling Zeebe
    bazel 学习一 简单java 项目运行
    一个好用node http keeplive agnet
    gox 简单灵活的golang 跨平台编译工具
    mailhog 作为smtp server mock工具
  • 原文地址:https://www.cnblogs.com/zhangxiaolei521/p/5987036.html
Copyright © 2011-2022 走看看