第十三章 事件

事件概念

JS与HTML之间的交互通过事件实现。事件就是文档或浏览器窗口中发生的一些的特定交互瞬间。可以使用侦听器(处理程序)来预定事件。以便事件发生时执行相应的代码。

事件流

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

I 事件冒泡

IE的事件流叫做事件冒泡,事件开始时由最具体的元素(文档中嵌套层次最深的那个节点)接收,逐级向上传播到较不具体的节点。

IE9.FF、chrome、safari冒泡到window对象。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Computed Styles Example</title>
</head>
<body
       <div id="myDiv">Click me!</div>
</body>
</html>

单击了DIV,那个这个click事件首先在div元素上发生,其次是body。click事件沿着DOM树向上传播。再每一个级节点上都会发生,直到document对象。

II事件捕获  

 由不太具体的节点应该更早接收的事件,而最具体的节点应该最后接收到事件。用意再于事件到达预定元素之前捕获它。

DOM流事件

DOM2级事件:规定事件流包括三个阶段: 事件捕获阶段,处于目标阶段 和事件冒泡阶段。 

事件捕获: 为截获事件提供机会。 然后是实际的目标接收到事件。最后一个阶段冒泡阶段,可以在这个阶段对事件做出响应

事件处理程序

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

HTML事件处理程序

<input type="button" value="click Me!" onclick="alert(event.type)">

通过event变量,可以直接访问事件对象。不用定义也不用从函数的参数列表中读取。
在这个函数的内部,this等于事件目标的元素。

<input type="button" value="click Me!" onclick="alert(this.type)">

HTML事件处理程序的缺点:

1、存在时差问题。用户再页面还没有解析事件处理程序的函数之前点击了按钮。会引发错误。

2、作用域链再不同浏览器中会导致不同结果。JS引擎遵循的标识符解析规则略有差异,很可能再访问非限定对象成员时出错。

3、需要修改事件时。需要修改HTML和JS俩处。

DOM0级事件处理程序

 将一个函数赋值给一个事件处理程序属性。优势在于简单。具有跨浏览器的优势。

每个元素都有自己的事件处理程序属性,将属性的值设为一个函数,就可以指定事件处理程序,程序中this引用当前元素。通过this访问元素的任何属性和方法,以这种方式会在事件的冒泡阶段被处理。

 var btn = document.getElementById("myBtn");
btn.onclick = function() {
    alert(this.id);       //“myBtn”
}

DOM2级事件处理程序

DOM2级定义了俩个方法用于处理指定和删除事件处理程序的操作:addEventListener()和 removeEventListener(): 接受三个参数 要处理的事件名、作为事件处理程序的函数、布尔值(true: 捕获阶段调用事件处理程序,false: 冒泡阶段调用)。

2级事件处理程序好处在于可以绑定多个事件处理程序。

 var btn = document.getElementById("myBtn");
btn.addEventListener("click", function() {
       alert(this.id);
}, false);

btn.addEventListener("click", function() {
       alert(this.tagName);
}, false);

removeEventListener,事件处理程序必须与传入addEvenListener()中的相同。

 var btn = document.getElementById("myBtn");
var hander = function() {
       alert(this.id);
}
btn.addEventListener("click", hander, false);

btn.removeListener("click", hander, false)

把事件处理程序添加到冒泡阶段,可以最大限度的兼容性浏览器。需要事件到达目标之前截获的时候才添加事件捕获。

 

IE 事件处理程序

IE浏览器使用attachEvent()和detachEvent()接受俩个参数: 事件处理程序名称 、事件处理函数。IE的事件处理程序不是以添加他们的顺序执行,以相反的顺序被触发。

 var btn = document.getElementById("myBtn");
var hander = function() {
       alert(this.id);
}
btn.attachEvent("onclick", hander, false);

btn.detachEvent("onclick", hander, false)

一个跨浏览器的事件处理程序

var Eventil = {
    addHandler: function(element, type, handler) {
           if(element.addEventListener) {
              element.addEventlistener(type, handler, false);
           }else if(element.attacthEvent) {
              element.attacthEvent("on" + type, handler);
           }else{
              element["on" + type] = handler;
           }
    },
    removeHandler: function(element, type, handler) {
           if(element.removeEvent) {
                 element.removeEvent(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(this.id);
}
EventUtil.addEventer(btn, "click',  hander);

事件对象

在触发DOM上的某个事件时,会产生一个事件对象event.这个对象中包含着所有事件有关的信息。

var btn = document.getElementById("myBtn");
btn.addEventListener(click, function(event) {
     alert(event.type); 
}, false);

再事件处理程序内部,对象this始终等于currentTarget(事件处理程序当前正在处理的那个元素)的值,而target则只包含事件的实际目标。

var btn = document.getElementById("myBtn");
btn.onclick = function(event) {
console.log(event.currentTarget == this); //true
console.log(event.target === this);          //true
}

如果事件处理程序存在于父节点中这些值就不一样了

document.body.onclick = function(event) {
   console.log(event.currentTarget === document.body); //true
   console.log(this === document.body);                         //this和currentTarget都等于document.body 因为事件是注册再这个元素上的
   console.log(event.target === document.getElementById("myBtn"));
// 真正的事件目标是mybtn
}

preventDefault(): 用于阻止特定事件的默认行为。只有canselable(是否可以取消默认事件)属性设置为true的事件,才可以使用preventDefault()。

stopPropagation(): 用于立即停止事件再DOM传播。

var link = document.getElementById("links");
link.onclick = function(event) {
    event.preventDefault();
    event.stopPropagation();
};
document.body.onclick = function(event) {
   console.log("Body Clicked")
}

event对象只存在于处理程序执行期间,事件处理程序执行完毕 立即被销毁。

IE中的事件对象

DOM0级方法添加事件处理程序时,event对象作为window对象的一个属性存在。

var btn = document.getElementById("myBtn");
btn.onclick = function() {
 var event = window.event;
console.log(event.type);  //click     
}

事件处理程序使用attachEvent()添加的,就会有一个event对象、作为参数被传入事件处理函数。

cancelBUbble:  默认值为false,设置为true可以取消事件冒泡。

returnValue: 默认值为true,设置为false可以取消事件默认行为。

srcElement: 事件的目标

type: 被触发的事件类型

跨浏览器的事件对象

var EventUtil = {
    addHandler: function(element, type, handler) {
           if(element.addEventListener) {
              element.addEventListener(type, handler, false);
           }else if(element.attachEvent) {
              element.attachEvent("on" + type, handler);
           }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;
           }
    },
    
    getEvent: function(event) {
        return event ? event : window.event;
    },
    
    getTarget: function(event) {
       return event.target || event.srcElement;
   },
   
   prevenrDefault: function(event) {
     if(event.preventDefault) {
        event.preventDefault();
     }else {
        event.returnValue = false;
     }
  },

  stopPropagation: function(event) {
   if(event.stopPropagation) {
      event.stopPropagation();
   }else {
      event.cancelBubble = true;
   }
 }

};

事件类型

1、Load事件

页面完全加载后(包括图像,JS文件,CSS文件等外部资源).就会触发window上面的load事件。

有俩种定义onload事件处理程序的方法

第一种使用JS指定事件处理程序

EventUtil.addHandler(window,"load", function(event) {
          console.log("loaded");
 });

第二种为<body>元素添加一个onload特性。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Computed Styles Example</title>
</head>
<body onload="console.log("loading")">
</body>
</html>

 

2、鼠标与滚轮事件

客户区坐标位置(页面坐标位置

clientX和clientY等于pageX和pageY

 屏幕坐标位置

鼠标事件发生时。不仅会有相对浏览器的窗口位置,还有一个相对于整个电脑屏幕的位置。

screenX和screenY属性相对整个屏幕的坐标。

3、鼠标按钮

对于mousedowm和mouseup ,在event对象中存在一个button属性,表示按下或释放。

button可能的值: 0:主鼠标按钮, 1:中间鼠标按钮 , 2 次鼠标按钮

event对象中detail属性

detail属性对于鼠标事件,包含一个数值,表示再给定位置上发生了多少单击。

鼠标滚轮事件

mousewheel:通过鼠标滚轮与页面交互。再垂直方向滚动页面时,就会触发。最终冒泡到document(IE8)对象或window对象。

wheelDelta属性: 鼠标滚轮向前滚动wheelDelta是120的倍数,向后滚是-120的倍数。多数情况只要指定滚动的方向,即检测wheelDelta的正负号。

 

内存和性能

事件委托:利用事件冒泡,只指定一个事件处理程序,管理一个类型的事件。

原文地址:https://www.cnblogs.com/zhangbaihua/p/5607922.html