• 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高级程序设计(第二版)》

  • 相关阅读:
    搭建LAMP及wordpress
    httpd2.4常用配置
    编译安装httpd 2.4
    https加密实现
    httpd常用配置
    源码编译安装bind
    安装mariadb二进制程序
    搭建互联网DNS构架
    搭建DNS服务
    主从及转发DNS搭建
  • 原文地址:https://www.cnblogs.com/zhangxiaolei521/p/5987036.html
Copyright © 2020-2023  润新知