乐趣区

关于javascript:爪哇学习笔记浏览器事件模型

概念

事件是您在编程时零碎内产生的动作或者产生的事件,零碎响应事件后,如果须要,您能够某种形式对事件做出回应。
在 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的区别

退出移动版