DOM系列:DOM事件模型

栏目: CSS3 · 发布时间: 5年前

内容简介:通过上一节的学习,对DOM事件有了一个简单的了解。但这只是学习DOM事件相关知识的起步点。今天来了解一下DOM事件的模型。在Web应用程序或Web网站中,可以通过使用者操作或系统的事件,达到相应的响应。而在JavaScript中,事件在未得到标准化之前,各浏览器就有一个事件模型 ——在基本事件模型中,要在某个事件发生时,调用指定的函数,也就是上一节中介绍的

通过上一节的学习,对DOM事件有了一个简单的了解。但这只是学习DOM事件相关知识的起步点。今天来了解一下DOM事件的模型。

基本事件模型

在Web应用程序或Web网站中,可以通过使用者操作或系统的事件,达到相应的响应。而在JavaScript中,事件在未得到标准化之前,各浏览器就有一个事件模型 —— 基本事件模型(Basic Event Model)

在基本事件模型中,要在某个事件发生时,调用指定的函数,也就是上一节中介绍的 事件处理程序 。这个程序会指定事件触发将会做什么样的事情。打个比方,当Web页面加载完所有资源之后,即 windowload 事件中做指定的事情:

window.onload = function () {
    // window的load事件发生时要做的事情...
}

除此之外,事件还可以由使用者的操作一些事情来触发事件。比如在按钮上绑定一个 click 事件:

<!-- HTML -->
<button>Click Me!</button>

// Script
let handler = function () {
    console.log(this)
}

document.querySelector('button').onclick = handler

上面的代码,当用户用鼠标点击按钮时会调用 handler() 函数,打印出来的 this 就是用户点击的按钮。像这样的做法,被称为 传统模型(Traditional Model)传统注册模型(Traditional Registration Model) 。这种事件模型也被称为 DOM0级模型

基本事件模型有一个典型的缺点,就是 只能注册一个事处处理程序 ,如果你想注册多个事件处理程序是行不通的。比如:

<!-- HTML -->
<button>单击我</button>

// Script
let handler1 = function () {
    console.log('Handler1:', this)
}

let handler2 = function () {
    console.log('Handler2', this)
}

document.querySelector('button').onclick = handler1
document.querySelector('button').onclick = handler2

当你点击 button 按钮时,浏览器控制台只会输出 hander2() 函数做的事情:

DOM系列:DOM事件模型

第一个函数 handler1() 不起作用。如果你想第一个函数也要起作用,那就需要使用接下来要说的事件模型 —— DOM Level 2模型

在基本事件模型中,如果要移除监听函数,可以通过给其事件赋值 null 来实现:

document.querySelector('button').onclick = null

DOM Level 2模型

DOM level 2模型属于W3C标准模型,现代浏览器都支持该模型。在该事件模型中,一次事件共有三个过程:

  • 事件捕获阶段(Capturing Phase) :事件从 document 一直向下传播到目标元素,依次检查经历过的节点是否绑定了事处监听函数(事件处理程序),如果有则执行,反之不执行
  • 事件处理阶段(Target Phase) :事件到达目标元素,触发目标元素的监听函数
  • 事件冒泡阶段(Bubbling Phase) :事件从目标元素冒泡到 document ,依次检查经过的节点是否绑定了事件监听函数,如果有则执行,反之不执行。

简而言之:事件一开始从文档的根节点流向目标对象(捕获阶段),然后在目标对向上被触发(目标阶段),之后再回溯到文档的根节点(冒泡阶段)。

DOM系列:DOM事件模型

图片来源于 W3C

DOM事件中这三个过程很复杂,但在这篇文章中不做深入阐述,如果感兴趣的话,后续的文章将会深入的探讨这方面的知识点。

回到DOM Level 2事件模型中,要注册事件,必须使用 addEventListener() 方法。比如下面这个示例:

let handler = function () {
    // window的load事件要做的事情...
}
window.addEventListener('load',handler, false)

在基本事件模型中提到过,基本事件模型只能注册一个事件,但在DOM Level 2事件模型中可以,比如前面提到的按钮的 click 事件,我们可以注册多个事件:

let handler1 = function () {
    console.log('handler1:', this)
}

let handler2 = function () {
    console.log('handler2', this)
}

document.querySelector('button').addEventListener('click', handler1, true)
document.querySelector('button').addEventListener('click', handler2, true)

这个时候点击按钮时, handler1()handler2() 两个函数都会被触发:

DOM系列:DOM事件模型

在DOM Level 2事件模型中,如果要移除事件处理程序,可以使用 removeEventListener() 方法。

let btn = document.getElementById('btn');
btn.addEventListener('click', handler, false);
btn.removeEventListener('click', handler, false);

虽然DOM Level 2事件模型是W3C标准事件模型,但低于IE9的浏览器是不支持这种事件模型。所以在JavaScript事件模型中,还有第三种事件模型 —— IE事件模型

IE事件模型

在IE事件模型中,需要使用 attachEvent()detachEvent() 方法来触发事件和移除事件。在IE事件模型中,其有两个过程:

  • 事件处理阶段(Target Phase) :事件到达目标元素,触发目标元素的监听函数
  • 事件冒泡阶段(Bubbling Phase) :事件从目标元素冒泡到 document ,依次检查经过的节点是否绑定了事件监听函数,如果有则执行

DOM Level 3事件模型

DOM Level 3事件模型是DOM Level 2的事件模型的升级版,在DOM Level 2事件模型的基础上添加了更多的事件类型:

  • UI事件 :当用户与页面上的元素交互时触发,如: loadscroll
  • 焦点事件 :当元素获得或失去焦点时触发,如: blurfocus
  • 鼠标事件 :当用户通过鼠标在页面执行操作时触发如: dbclickmouseup
  • 滚轮事件 :当使用鼠标滚轮或类似设备时触发,如: mousewheel
  • 文本事件 :当在文档中输入文本时触发,如: inputchange
  • 键盘事件 :当用户通过键盘在页面上执行操作时触发,如: keydownkeypress
  • 合成事件 :当为IME(输入法编辑器)输入字符时触发,如: compositionstart
  • 变动事件 :当底层DOM结构发生变化时触发,如: DOMsubtreeModified

同时DOM3级事件也允许使用者自定义一些事件。在自定义事件称之为 自定义事件模型

自定义事件模型

事件模型的实现从 设计模式 的角度来看,是一种观察者模式或者也叫发布订阅模式,订阅者订阅一个消息,发布者发布这个消息,订阅者收到消息,这是一种数据流动的方式,使用这个模式的好处是,可以有多个订阅者,一个发布者,发布一条消息,可被多个订阅者收到。

比如下面这样的一个事件模型:

;(function(global){
    class Events {
        constructor(){
            this.cache = {};
            this.onceKeys = [];
        }
        on(key, fn){
            if(!this.cache[key]) this.cache[key] = [];
            this.cache[key].push(fn);
        }
        one(key, fn){
            this.cache[key]=[];
            this.on(key, fn);
            this.onceKeys.push(key);
        }
        off(key, fn){
            if(this.cache[key]) this.cache[key] = fn ? this.cache[key].filter(v=>v !== fn) : [];
        }
        emit(key, ...args){
            if(this.cache[key]){
                this.cache[key].forEach(v=>v.apply(null, args))
                if(this.onceKeys.includes(key)){
                    this.cache[key] = [];
                    this.onceKeys = this.onceKeys.filter(v=>v!==key);
                }
            }
        }
    }

    global.Events = new Events();
})(this)

这是一个简单的自定义事件型型:

on()
emit()
off
one

如果要使用,可以这样:

Events.on('cus', (a, b) => console.log(a+b))
Events.emit('cus', 1, 2); // => 3
Events.off('cus');
Events.emit('cus', 1, 2)

// 只触发一次
Events.one('once', a => console.log(a))
Events.emit('once', 1); // => 1
Events.emit('once', 2);

从事件模型中学到

从DOM事件模型上,我们可以学到很多。可以在项目中使用类似的解耦的概念。应用中的模块可以有很高的很复杂度,只要它的复杂度被封装隐藏在一套简单的接口背后。很多前端框架(比如 Backbone.js )都是重度基于事件的,使用发布/订阅(Publish & Subscribe)的方式来处理跨模块间的通信,这点跟DOM非常相似。

基于事件的架构是极好的。它提供给我们一套非常简单通用的接口,通过针对这套接口的开发,我们能完成适应成千上万不同设备的应用。通过事件,设备们能准确地告诉我们正在发生的事情以及发生的时间,让我们随心所欲地做出响应。我们不再顾虑场景背后具体发生的事情,而是通过一个更高层次的抽象来写出更加令人惊艳的应用。

总结

这篇文章简单的介绍了DOM事件的模型。在JavaScript中常见的事件模型有: DOM基本事件模型DOM Level 2事件模型IE事件模型DOM Level 3事件模型自定义事件模型 。每种事件模型都有其自己独具的特性。只有了解了DOM事件模型之后,才可以为后续的DOM事件打下一个基础。

由于自己是JavaScript的初学者,如果文章中有不对之处,烦请各位大神拍正。如果你觉得这篇文章对你有所帮助,打个赏,让我有更大的动力去创作。(^_^)。

DOM系列:DOM事件模型

大漠

常用昵称“大漠”,W3CPlus创始人,目前就职于手淘。对HTML5、CSS3和Sass等前端脚本语言有非常深入的认识和丰富的实践经验,尤其专注对CSS3的研究,是国内最早研究和使用CSS3技术的一批人。CSS3、Sass和Drupal中国布道者。2014年出版《 图解CSS3:核心技术与案例实战 》。

如需转载,烦请注明出处: https://www.w3cplus.com/javascript/dom-model.html


以上所述就是小编给大家介绍的《DOM系列:DOM事件模型》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

算法分析-有效的学习方法(影印版)

算法分析-有效的学习方法(影印版)

Jeffrey J.McConnell / 高等教育出版社 / 2003-03-01 / 28.0

本书主要目标是提高读者关于算法对程序效率的影响等问题的认知水平,并培养读者分析程序中的算法所必需的技巧。各章材料以激发读者有效的、协同的学习方法的形式讲述。通过全面的论述和完整的数学推导,本书帮助读者最大限度地理解基本概念。 本书内容包括促使学生参与其中的大量程序设计课题。书中所有算法以伪码形式给出,使得具备条件表达式、循环与递归方面知识的读者均易于理解。本书以简洁的写作风格向读者介绍了兼具......一起来看看 《算法分析-有效的学习方法(影印版)》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码