事件:什么是事件流?什么是事件模型?什么是事件代理?什么是事件对象?

  1. 什么是事件流?
    ans:事件流:描述从页面中接收事件的顺序
    (1) 事件冒泡:事件开始时由最具体的元素接收,然后逐级向上传播到较为不具体的节点
    (2) 事件捕获:不太具体的节点先接收事件,而具体的节点最后接收到事件
    (3) “DOM2级事件”:规定事件流包括三个阶段:事件捕获阶段、处于目标阶段、事件冒泡阶段

  2. 事件“捕获”和“冒泡”执行次数和事件的执行顺序

ans:按照DOM2级事件
(1) 事件执行次数:元素绑定多少个事件,就执行多少次。前提是:

  • 事件确实被触发
  • 事件绑定几次就算几个事件,就算类型和功能完全一样也不会被覆盖

(2) 事件执行顺序:关键是判断是否为目标元素

  • 非目标元素:根据W3C的标准执行:捕获->目标元素->冒泡(不依据事件绑定顺序)
  • 目标元素:依据事件绑定顺序:先绑定的事件先执行(不依据捕获冒泡标准)
  • 最终顺序:父元素捕获->目标元素事件1->目标元素事件2->子元素捕获->子元素冒泡->父元素冒泡
  • 子元素事件执行前提是事件确实“落”到子元素布局区域上,而不是简单的具有嵌套关系
  1. 事件模型
    ans:即事件处理程序。事件就是用户或浏览器自身执行的某种动作,而响应某个事件的函数就叫做事件处理程序(或事件监听器)。浏览器的事件模型,就是 通过监听函数对事件作出反应。

(1) HTML事件处理程序:HTML的 on- 属性

<input type="button" value="Click Me" onclick="doSomething()">

元素的事件监听属性,都是on+事件名,例如onload, onclick。使用这个方法指定的监听代码,只会在冒泡阶段触发。
缺点:HTML代码和JavaScript代码高度耦合,若要更换事件处理程序,则要同时改动HTML代码和JavaScript代码。另外,若用户在HTML元素一出现在页面上就触发相应事件,而此时事件处理程序若不具备执行条件(例如函数还没被解析出来),就会出现错误。

(2) DOM0级事件
将一个函数赋值给事件处理程序 属性,见代码:

var btn = document.getElementById("myBtn");
btn.onclick = function() {
    console.log("Clicked");
}

用这种方式指定的监听函数,同样只会在冒泡阶段触发。
缺点:同一个事件只能定义一个监听函数,如果定义两次onclick属性,后面的会覆盖前面的。

(3)DOM2级事件处理程序
“DOM2级事件”定义了两个方法:addEventListener和 removeEventListener,所有的DOM节点都包含这两个方法,它们都接收三个参数:
addEventListener(要处理的事件名,作为事件处理程序的函数,布尔值)
布尔值:true: 在捕获阶段调用事件处理程序;false:在冒泡阶段调用
见代码:

var btn = document.getElementById("myBtn");
btn.addEventListener("click", function() {
    console.log(this.id);
}, false);
btn.addEventListener("click", function() {
    console.log("hello world!");
}, false);

通过addEventListener()添加的事件处理程序只能通过removeEventListener()来移除,三个参数必须完全相同,所以添加的匿名函数无法删除

优点:

  • 同一个事件可以添加多个监听函数。
  • 能够指定在哪个阶段(捕获阶段还是冒泡阶段)触发监听函数。
  • 除了 DOM 节点,其他对象(比如window、XMLHttpRequest等)也有这个接口,它等于是整个 JavaScript 统一的监听函数接口。
  1. 什么是事件代理?
    ans:由于事件会在冒泡阶段从子节点传递到父节点,所以可以通过将子节点的监听函数定义在父节点上,由父节点的监听函数统一处理多个子元素的事件。此即为事件代理。

  2. 什么是事件对象?
    ans:在触发DOM上的某个元素时,会产生一个事件对象event,作为参数传给监听函数。里面包含着所有与事件有关的信息,包括导致事件的元素、事件的类型等。例如鼠标操作导致的事件中,会包含鼠标位置的信息。浏览器原生提供一个Event对象,所有的事件都是这个对象的实例,或者说继承了Event.prototype对象。Event对象本身就是一个构造函数,可以用来生成新的实例。

event = new Event(type, options);

第一个参数type是字符串,表示事件的名称;第二个参数options是一个对象,表示事件对象的配置。该对象主要有下面两个属性。

  • bubbles:布尔值,可选,默认为false,表示事件对象是否冒泡。
  • cancelable:布尔值,可选,默认为false,表示事件是否可以被取消,即能否用Event.preventDefault()取消这个事件。
  1. addEventListener() 和attachEvent()的区别?
    ans:attachEvent()和detachEvent()为IE事件处理程序中定义的两个方法。
    attachEvent()的特点:
  • attachEvent()和detachEvent()接收两个参数:attachEvent(事件处理程序名称,事件处理程序函数)
var btn = document.getElementById("myBtn");
btn.attachEvent("onclick", function() {       // 注意第一个参数时“onclick”,和 addEventListener() 中的“click”有所区别
    console.log("Clicked");
})
  • 通过attachEvent()添加的事件处理程序都会被添加到冒泡阶段
  • 和addEventListener() 一样,attachEvent()可以为一个元素添加多个事件处理程序,通过detachEvent()移除,同样需要每个参数保持一致,所以匿名函数也没法移除。
  • attachEvent(),事件处理程序在全局作用域中运行,即this === window;而DOM0级事件处理程序中,程序中的this指向当前元素,即事件处理程序在元素的作用域中运行。
  • 与DOM方法不同,通过attachEvent()添加的事件处理程序,以跟添加顺序相反的顺序被触发。以下代码,先看到"hello world!",再看到"Clicked"
var btn = document.getElementById("myBtn");
btn.attachEvent("onclick", function() {
    console.log("Clicked");
}) 
btn.attachEvent("onclick", function() {
    console.log("hello world!")
})

总结

  • addEventListener() 传递三个参数,attachEvent()传递两个参数,且attachEvent()传递的事件名前面必须加 on-
  • addEventListener() 先绑定先触发,attachEvent()先绑定后触发
  • addEventListener() 添加的事件处理程序在元素的作用域中运行,attachEvent()添加的事件处理程序在全局作用域中运行
  • addEventListener() 添加的事件处理程序可以选择添加到捕获或冒泡阶段,attachEvent()添加的事件处理程序只被添加到冒泡阶段
  1. 如何定义跨浏览器的事件处理程序?
    ans:要保证处理事件的代码能在大多数浏览器上一致的运行,只用关注冒泡阶段
    代码如下:
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;
        }
    }
}

var btn = document.getElementById("myBtn");
var handler = function() {
    console.log("Clicked");
}
EventUtil.addHandler(btn, "click", handler);
EventUtil.removeHandler(btn, "click", handler);

先检测传入的元素中是否存在DOM2级方法,若存在的时IE的方法,则采取第二种方案,最后一种即采用DOM0级方案。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值