事件

195 阅读4分钟
事件流

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


浏览器事件如单击事件,当你单击按钮的同时,你也单击了按钮的容器元素,甚至也单击整个页面.

  1. 事件冒泡 ( IE 事件流)
  • 事件开始时由最具体的元素接收,然后逐级向上传播到具体的节点
    <!DOCTYPE html>
    <html>
    <head>
     <title>Event Bubbling Example</title>
    </head>
    <body>
     <div id="myDiv">Click Me</div>
    </body>
    </html> 
  • 如果单击了页面的div元素,事件的传播顺序为: div ----> body----> html -----> document
  1. 事件捕获(Netscape)
  • 不太具体的节点应该更早接收到事件,而最具体的节点最后接收到事件。
  • 此时上面的单击事件的传播顺序为:document -----> html -----> body------> div
  1. Dom事件流
  • DOM2级事件规定的事件流包括三个阶段:事件捕获阶段处于目标阶段事件冒泡阶段
  • 此时上面的单击事件的传播顺序为:(document -----> html -----> body) 事件捕获阶段------> (div)处于目标阶段----> (body----> html -----> document)事件冒泡阶段
事件处理程序

事件就是用户或浏览器自身执行的某种动作: 如 click(单击事件)


响应某个事件的函数就叫做事件处理程序(或事件侦听器)


事件处理程序的名字以"on"开头,如onclick onload

  1. Html事件处理程序
  • 元素中的事件属性特性值为js代码,一般不采用。
  <input type="button" value="Click Me" onclick="alert('Clicked')" /> 
  • 元素中的事件属性特性值为:要执行的具体操作(函数调用)------->这样会创建一个封装元素属性值函数,该函数中有一个局部变量 event,也就是事件对象访问局部变量event和元素属性值:
  //调用局部变量event
  <input type="button" value="Click Me" onclick="alert(event.type)">  //打印结果click
  //调用元素属性值
  <input type="button" value="Click Me" onclick="alert(this.value)"> //打印结果 Click Me
//调用封装函数内的局部变量event和元素属性值
<body>
     <input type="button" value="hahhahhah" onclick="test(event,value)">点击这里 </input>
     <script>
         function test(event,value) {
             console.log(event.type+""+value);
         }
     </script>
 </body>
  • 动态创建的封装函数通过with 扩充作用域 若是普通元素如:
   <input type="button" value="Click Me" onclick="alert(this.value)"> 

动态函数扩充作用域:

function(){
   with(document){
     with(this){
     //元素属性值
     }
   }
} 

若是表单元素如:

  <form method="post">
     <input type="text" name="username" value="">
     <input type="button" value="Echo Username" onclick="alert(username.value)">
  </form> 

动态函数扩充作用域:

function(){
   with(document){
     with(this.form){
       with(this){
       //元素属性值
       }
     }
   }
} 
  1. Dom0 级事件处理程序
     <button id="myBtn">点击</button>
     <script>
         var btn = document.getElementById("myBtn");
         btn.onclick = function () {
             // this为当前元素引用,event为局部变量
             alert(this.id+""+event.type);  //"myBtnclick"
             btn.onclick = null;
         };
         document.body.appendChild(btn);
     </script>
  • this 为绑定的元素对象引用
  • 将如onclick等事件处理程序设置为null就能取消单击事件
  1. Dom2 级事件处理程序
  • 使用 addEventListener() removeEventListener() 指定和删除事件处理程序-----> 有个参数:事件名处理函数,布尔值(捕获阶段处理用true,冒泡阶段处理用false
  • 要使移除的是同一个事件处理函数,必须传的是函数变量,而不是匿名函数(会导致addremove的不是同一个)
    var btn = document.getElementById("myBtn");
    var handler = function(){
     alert(this.id);
    };
    btn.addEventListener("click", handler, false);
    //这里省略了其他代码
    btn.removeEventListener("click", handler, false); 
  1. IE 事件处理程序
  • IE 实现了与 DOM 中类似的两个方法:attachEvent() detachEvent()。这两个方法接受相同的两个参数:事件名称处理函数
  • IE 只支持事件冒泡
  • 事件名前需要加 on
    var btn = document.getElementById("myBtn");
    var handler = function(){
     alert("Clicked");
    };
    btn.attachEvent("onclick", handler);
    //这里省略了其他代码
    btn.detachEvent("onclick", handler); 
  1. 浏览器的事件处理程序
       var EventUtil = {
             addHandler: function (element, type, handler) {
                 //判断是否是dom2级的
                 if (element.addEventListener) {
                     element.addEventListener(type, handler, false);
                 // 判断是否是 IE
                 } else if (element.attachEvent) {
                     element.attachEvent("on" + type, handler);
                 } 
                 //最后就是dom0级的
                 else {
                     element["on" + type] = handler;
                 }
             },
             removeHandler: function (element, type, handler) {
                 if (element.removeEventListener) {
                     element.removeEventListener(type, handler, false);
                 } else if (element.detachEvent) {
                     element.detachEvent("on" + type, handler);
                 } else {
                     element["on" + type] = null;
                 }
             }
        };

例子:

    var btn = document.getElementById("myBtn");
    var handler = function(){
     alert("Clicked");
    };
    EventUtil.addHandler(btn, "click", handler);
    //这里省略了其他代码
    EventUtil.removeHandler(btn, "click", handler); 
事件对象

常见的属性方法

preventDefault():取消事件的默认行为 -------> defaultPrevented 来判断是否已经取消(Boolean值)


stopPropagation() :取消事件的进一步捕获冒泡-------->bubbles 来判断是否已经取消


target:获取事件的目标对象Element


detail :事件的详细信息


type: 被触发的事件类型


等等 统一处理多个事件:

var btn = document.getElementById("myBtn");
var handler = function(event){ 
   switch(event.type){
       case "click":
       alert("Clicked");
       break;
       case "mouseover":
       event.target.style.backgroundColor = "red";
       break;
       case "mouseout":
       event.target.style.backgroundColor = "";
       break;
   }
};
btn.onclick = handler;
btn.onmouseover = handler;
btn.onmouseout = handler; 

跨浏览器的事件:

var EventUtil = {
   addHandler: function(element, type, handler){
   //省略的代码
   },
   getEvent: function(event){
      // event为false时去获取IE的事件对象window.event
       return event ? event : window.event;
   },
   getTarget: function(event){
       //IE的目标对象event.srcElement
       return event.target || event.srcElement;
   },
   preventDefault: function(event){
     if (event.preventDefault){
       event.preventDefault();
     } 
     else {
       //IE的取消默认事件
       event.returnValue = false;
     }
   },

   removeHandler: function(element, type, handler){
   //省略的代码
   },
   stopPropagation: function(event){ 
    if (event.stopPropagation){
     event.stopPropagation();
   } 
   else {
    //IE的取消冒泡
     event.cancelBubble = true;
   }
   }
}; 
事件委托

1. 事件委托利用了事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件.

// html
// li 会冒泡到 ul,还可以在更上层的元素定义处理程序
<ul id="myLinks">
   <li id="goSomewhere">Go somewhere</li>
   <li id="doSomething">Do something</li>
   <li id="sayHi">Say hi</li>
</ul> 
// js
var list = document.getElementById("myLinks");
EventUtil.addHandler(list, "click", function(event){
   event = EventUtil.getEvent(event);
   //获取目标对象element
   var target = EventUtil.getTarget(event);
   //通过目标对象的id来判断做什么处理
   switch(target.id){
     case "doSomething":
       document.title = "I changed the document's title";
       break;
     case "goSomewhere":
       location.href = "http://www.wrox.com";
       break;
     case "sayHi":
       alert("hi");
     break;
 }
}); 
  1. 移除事件处理程序,除了使用removeChild()replaceChild()方法,更多的使用用 innerHTML```` 替换页面中某一部分,但要注意在替代时需使原先node绑定事件为null.
 <body>
    <div id="myDiv">
        <input type="button" value="Click Me" id="myBtn">
       </div>
       <script type="text/javascript">
        var btn = document.getElementById("myBtn");
        btn.onclick = function(){
        //先执行某些操作
        btn.onclick = null; //移除事件处理程序
        //此时button按钮被替换成Processing...文本
        document.getElementById("myDiv").innerHTML = "Processing...";
        };
       </script> 
 </body>