概念

事件是您在编程时零碎内产生的动作或者产生的事件,零碎响应事件后,如果须要,您能够某种形式对事件做出回应。
在 Web 中, 事件在浏览器窗口中被触发并且通常被绑定到窗口外部的特定局部 — 可能是一个元素、一系列元素、被加载到这个窗口的 HTML 代码或者是整个浏览器窗口。

事件流

事件流形容的是页面中承受事件的程序。

“DOM2级事件“规定的事件流包含三个阶段:事件捕捉阶段、处于指标阶段和事件冒泡阶段。——《JavaScript高级程序设计》

依据W3C模型,事件首先被指标元素所捕捉,而后向上冒泡。——《基于MVC的JavaScript Web富利用开发》

事件捕捉

从顶层的父节点开始触发事件,从外到内流传,到触发事件originTarget完结。

事件冒泡

从内层originTarget节点开始触发事件,由外向外流传,逐级冒泡直到顶层节点完结。

留神:不是所有的事件都反对事件冒泡的,blur、focus、load、unload、mouseenter、mouseleave以及自定义事件不反对冒泡。

阻止事件流传

  • e.stopPropagation():大家常常听到的可能是阻止冒泡,实际上这个办法不只能阻止冒泡,还能阻止捕捉阶段的流传。
  • e.stopImmediatePropagation():阻止监听同一事件的其余事件监听器被调用。如果多个事件监听器被附加到雷同元素的雷同事件类型上,当此事件触发时,它们会按其被增加的程序被调用。如果在其中一个事件监听器中执行stopImmediatePropagation(),那么剩下的事件监听器都不会被调用。

阻止事件默认行为

e.preventDefault()能够阻止事件的默认行为产生,默认行为是指:点击a标签就转跳到其余页面、拖拽一个图片到浏览器会主动关上、点击表单的提交按钮会提交表单等等,因为有的时候咱们并不心愿产生这些事件,所以须要阻止默认行为。

留神

  1. 只有cancelable属性为true的事件才能够应用preventDefault()办法来勾销其默认行为
  2. 既要终止冒泡又要阻止默认行为时,间接return false即可

事件处理器(事件监听器)

用来响应事件的函数或代码块

事件处理程序HTML属性(内联事件处理程序)

属性值就是当事件产生时要运行的JavaScript代码

<input id="btn" type="button" onclick="handleClick(this.value)" value="hello"/><script>    function handleClick(value){        console.log(window.event);        console.log(event);        console.log(event.target);        console.log('this', this); // window        console.log(value);  // hello        console.log(this.value);  // undefined    }</script>
通过这种形式指定时,会创立一个封装着元素属性值得函数。这个函数中有一个局部变量event(即事件对象)。通过event变量,能够间接拜访事件对象,你不必本人定义它,也不必从函数的参数列表中读取(经测试,在chrome、和IE11中不必从函数的参数列表读取,然而在fireFox中则须要)。在这个函数外部,this值等于事件的指标元素。——《JavaScript高级编程》

下面这段话咱们能够了解为:通过html属性指定事件处理程序时,在指定的处理函数外再包装一层函数,而后将这个新函数赋值给btn.onclick(见DOM0级事件处理程序),这样新函数作用于内的this就指向了事件指标元素。然而在具体的事件处理函数handler外部,因为没有 具体的调用对象,在非严格模式下它外部的this指向window

DOM0级事件处理程序

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

DOM2级事件处理程序

次要就是addEventListenerremoveEventListener两个办法,它们都承受3个参数:要解决的事件名、事件处理函数、一个布尔值(示意是否启用事件捕捉),应用它们的次要益处就是能够增加多个事件处理程序。

留神:如果监听的函数是匿名函数,没有任何援用指向它,在不销毁这个元素的前提下,这个监听是无奈被移除的。

IE事件处理程序(IE7、IE8)

IE实现了attachEvent()和detachEvent()。这两个办法都承受两个参数:事件处理程序名称和事件处理函数。

  • 在应用这两个函数时,事件处理程序会在全局作用域中运行,因而this指向window
  • 这些事件处理程序不是以增加它们的形式运行的,而是以相同的程序触发

跨浏览器的事件处理程序

function addHandler(target, eventType, handler) {    if (target.addEventListener) { // DOM2 Events        target.addEventListener(eventType, handler, false);    } else if (target.attachEvent) { // IE        target.attachEvent('on' + eventType, handler);    } else {        target['on' + eventType] = handler;    }}function removeHandler(target, eventType, handler) {    if (target.removeEventListener) {        target.removeEventListener(eventType, handler, false);    } else if (target.detachEvent) {         target.detachEvent('on' + eventType, handler);    } else {        target['on' + eventType] = null;    }}// 阻止事件 (次要是事件冒泡,因为IE不反对事件捕捉)function stopPropagation(e) {    if (e.stopPropagation) {        e.stopPropagation(); // 规范w3c    } else {        e.cancelBubble = true; // IE    }}// 勾销事件的默认行为function preventDefault(e) {    if (e.preventDefault) {        e.preventDefault(); // 规范w3c    } else {        e.returnValue = false; // IE    }}

事件委托

艰深来讲,就是把一个元素响应事件(click、keydown等)的函数委托到另一个元素。
通常会把一个或一组元素的事件委托到它的父层或者更外层元素上,真正绑定事件的是外层元素,当事件响应到须要绑定的元素上时,会通过事件冒泡机制触发。

自定义事件

非IE浏览器

  • 形式一

    // 创立事件,参数为事件类型var event = new Event('Event'); // 初始化事件// initEvent(type: string, bubbles?: boolean, cancelable?: boolean): void;event.initEvent('build', true, true); elem.addEventListener('build', function(e) {  // do something}, false);// 触发事件elem.dispatchEvent(event);
  • 形式二
    Event的构造函数定义为new(type: string, eventInitDict?: EventInit): Event;
    其中EventInit的定义为:

    interface EventInit {  bubbles?: boolean; // 是否冒泡,默认false  cancelable?: boolean; // 是否可勾销,默认false  composed?: boolean; //是否是否会在shadow DOM根节点之外触发侦听器,默认false}
    // 创立及初始化事件var event = new Event('build', {  bubbles: true,  cancelable: true});elem.addEventListener('build', function(e) {  // do something}, false);// 触发事件elem.dispatchEvent(event);

IE8及之前浏览器

var event = document.createEventObject(); // 不承受任何参数// 给event的属性赋值...elem.fireEvent('onclick', event); // 触发事件

在调用fireEvent()办法时,会主动为event对象增加srcElementtype属性;其余属性则都是必须通过手工增加的。

事件对象

事件对象分为DOM中的事件对象和IE中的事件对象,应该是为了兼容,Event对象的中的属性和办法将这两种事件对象的属性办法都包含进去了。

DOM中事件对象的属性/办法

  • bubbles: boolean表明事件是否冒泡
  • cancelable: boolean表明是否能够勾销事件默认行为
  • composed: boolean是否是否会在shadow DOM根节点之外触发侦听器
  • currentTarget: EventTarget以后正在调用事件处理函数的那个元素
  • defaultPrevented: boolean为true示意曾经调用了preventDefault()办法
  • eventPhase: number调用事件处理程序的阶段:1示意捕捉阶段,2示意“处于指标”,3示意冒泡阶段
  • isTrusted: boolean表明是否是浏览器生成的事件
  • target: EventTarget事件的指标
  • initEvent(type: string, bubbles?: boolean, cancelable?: boolean): void;
  • preventDefault(): void
  • stopImmediatePropagation(): void
  • stopPropagation(): void
  • type: string事件类型

IE中的事件对象的属性/办法

  • cancelBubble: boolean默认值为false,但将其设置为true就能够勾销事件冒泡
  • returnValue: boolean默认值为true,但将其设置为false就能够勾销事件的默认行为
  • srcElement: Element事件的指标,对应target
  • type: string事件类型(IE中的type与DOM中的type是雷同的)

留神targetcurrentTarget的区别