说说JavaScript中的事件模型

news/2024/11/19 7:41:54/文章来源:https://www.cnblogs.com/smileZAZ/p/18198429

一、事件与事件流

javascript中的事件,可以理解就是在HTML文档或者浏览器中发生的一种交互操作,使得网页具备互动性, 常见的有加载事件、鼠标事件、自定义事件等

由于DOM是一个树结构,如果在父子节点绑定事件时候,当触发子节点的时候,就存在一个顺序问题,这就涉及到了事件流的概念

事件流都会经历三个阶段:

  • 事件捕获阶段(capture phase)
  • 处于目标阶段(target phase)
  • 事件冒泡阶段(bubbling phase)

事件冒泡是一种从下往上的传播方式,由最具体的元素(触发节点)然后逐渐向上传播到最不具体的那个节点,也就是DOM中最高层的父节点

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><title>Event Bubbling</title></head><body><button id="clickMe">Click Me</button></body>
</html>

然后,我们给button和它的父元素,加入点击事件

var button = document.getElementById('clickMe');button.onclick = function() {console.log('1.Button');
};
document.body.onclick = function() {console.log('2.body');
};
document.onclick = function() {console.log('3.document');
};
window.onclick = function() {console.log('4.window');
};

点击按钮,输出如下

1.button
2.body
3.document
4.window

点击事件首先在button元素上发生,然后逐级向上传播

事件捕获与事件冒泡相反,事件最开始由不太具体的节点最早接受事件, 而最具体的节点(触发节点)最后接受事件

二、事件模型

事件模型可以分为三种:

  • 原始事件模型(DOM0级)
  • 标准事件模型(DOM2级)
  • IE事件模型(基本不用)

原始事件模型

事件绑定监听函数比较简单, 有两种方式:

  • HTML代码中直接绑定
<input type="button" onclick="fun()">
  • 通过JS代码绑定
var btn = document.getElementById('.btn');
btn.onclick = fun;

特性

  • 绑定速度快

DOM0级事件具有很好的跨浏览器优势,会以最快的速度绑定,但由于绑定速度太快,可能页面还未完全加载出来,以至于事件可能无法正常运行

  • 只支持冒泡,不支持捕获

  • 同一个类型的事件只能绑定一次

<input type="button" id="btn" onclick="fun1()">var btn = document.getElementById('.btn');
btn.onclick = fun2;

如上,当希望为同一个元素绑定多个同类型事件的时候(上面的这个btn元素绑定2个点击事件),是不被允许的,后绑定的事件会覆盖之前的事件

删除 DOM0 级事件处理程序只要将对应事件属性置为null即可

btn.onclick = null;

标准事件模型

在该事件模型中,一次事件共有三个过程:

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

事件绑定监听函数的方式如下:

addEventListener(eventType, handler, useCapture)

事件移除监听函数的方式如下:

removeEventListener(eventType, handler, useCapture)

参数如下:

  • eventType指定事件类型(不要加on)
  • handler是事件处理函数
  • useCapture是一个boolean用于指定是否在捕获阶段进行处理,一般设置为false与IE浏览器保持一致

举个例子:

var btn = document.getElementById('.btn');
btn.addEventListener(‘click’, showMessage, false);
btn.removeEventListener(‘click’, showMessage, false);

特性

  • 可以在一个DOM元素上绑定多个事件处理器,各自并不会冲突
btn.addEventListener(‘click’, showMessage1, false);
btn.addEventListener(‘click’, showMessage2, false);
btn.addEventListener(‘click’, showMessage3, false);
  • 执行时机

当第三个参数(useCapture)设置为true就在捕获过程中执行,反之在冒泡过程中执行处理函数

下面举个例子:

<div id='div'><p id='p'><span id='span'>Click Me!</span></p >
</div>

设置点击事件

var div = document.getElementById('div');
var p = document.getElementById('p');function onClickFn (event) {var tagName = event.currentTarget.tagName;var phase = event.eventPhase;console.log(tagName, phase);
}div.addEventListener('click', onClickFn, false);
p.addEventListener('click', onClickFn, false);

上述使用了eventPhase,返回一个代表当前执行阶段的整数值。1为捕获阶段、2为事件对象触发阶段、3为冒泡阶段

点击Click Me!,输出如下

P 3
DIV 3

可以看到,pdiv都是在冒泡阶段响应了事件,由于冒泡的特性,裹在里层的p率先做出响应

如果把第三个参数都改为true

div.addEventListener('click', onClickFn, true);
p.addEventListener('click', onClickFn, true);

输出如下

DIV 1
P 1

两者都是在捕获阶段响应事件,所以divp标签先做出响应

IE事件模型

IE事件模型共有两个过程:

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

事件绑定监听函数的方式如下:

attachEvent(eventType, handler)

事件移除监听函数的方式如下:

detachEvent(eventType, handler)

举个例子:

var btn = document.getElementById('.btn');
btn.attachEvent(‘onclick’, showMessage);
btn.detachEvent(‘onclick’, showMessage);

  

如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/707892.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据库系统概念 B+树 学习笔记

因为画图所以是纸质的,在这留个档本文来自博客园,作者:lei_yu,转载请注明原文链接:https://www.cnblogs.com/lytql/p/18198419

完整的牛津3000词汇表及牛津5000词汇表

Oxford 3000(牛津3000词)列出了每个英语学习者需要掌握的3000个核心词汇。根据牛津英语语料库中的频率和与英语学习者的相关性进行选择;涵盖CEFR等级A1-B2学习者需要掌握的总单词的75%左右;每个单词都与CEFR等级对标,指导学习者明确所处等级应该掌握的单词;权威专家指导—…

Redis 的安装与配置详解【Redis系列一】

本文介绍了什么是 Redis,安装,以及详细的配置项的介绍。〇、前言 关于 Redis 在日常开发中还是用的比较多的,特别是在秒杀、消息队列、排行榜等数据交互时效要求较高的场景,Redis 都可以轻松应对。 本文将针对 Redis 进行简单介绍,以及如何安装,并罗列下全部配置项。后续…

【土地效能大探秘】低效利用土地如何认定?

在快速推进的城市化进程中,土地资源的有效利用成为了关乎经济可持续发展的关键议题。今天,我们就来深入探讨一个核心问题:低效利用土地是如何被认定的?这不仅关系到土地资源的优化配置,也是提升城市发展质量的关键一环。低效利用土地的定义首先,我们需要明确“低效利用土…

Android 15 的新功能与适配

Android 15 的新功能与适配前台服务变化 前台服务一直是比较损耗电池寿命的操作,在 Android 15 Beta 2 里,**dataSync 和 mediaProcessing 的前台服务类型现在有大约 6 小时的超时时间**,之后系统将调用 Android 15 新的 Service.onTimeout(int, int)方法,之后该服务就不会…

Django自定义模板标签与过滤器

title: Django自定义模板标签与过滤器 date: 2024/5/17 18:00:02 updated: 2024/5/17 18:00:02 categories:后端开发tags:Django模版 自定义标签 过滤器开发 模板语法 Python后端 前端集成 Web组件Django模板系统基础 1. Django模板语言概述 Django模板语言(DTL)是一种用于在…

3 从网线到网络设备

目录1 信号在网线和集线器中传输2 交换机的包转发操作3 路由器的包转发操作1 信号在网线和集线器中传输 TCP 控制信息也叫 TCP 头部,但从以太网和 IP 传输网络包的角度来看,TCP 头部并不算是“头部”,只能算是“数据”img1 集线器将信号发送给所有连接在它上面的线路2 交换机…

达梦表级触发器

// 达梦触发器CREATE OR REPLACE TRIGGER "K_BASIC"."B_BASE_ENGINEERING_CATEGORY TO B_PROJECT_INVESTMENT" AFTER UPDATE OR INSERT ON "K_BASIC"."B_BASE_ENGINEERING_CATEGORY" REFERENCING OLD ROW AS "OLD" NEW ROW…

NotePad在每行前面或后面添加一些内容

文本文件的每行前面或后面添加一些内容,如给下面文件每一行后面添加;方法 1. 下载文本编辑器 NotePad++ 下载地址:https://notepad-plus.en.softonic.com/download 2. 在每行后面添加内容使用快捷键Ctrl+H打开“替换对话框”,在每行的开头添加内容。 勾选左下角的“正则表达…

C-5-初次接触-全-

C#5 初次接触(全)原文:zh.annas-archive.org/md5/2E6DA4A6D245D14BD719EE0F1D9AAED3 译者:飞龙 协议:CC BY-NC-SA 4.0前言 C#是一种非常富有表现力和强大的语言,让您可以专注于应用程序而不是低级样板。在过去的十年中,C#编译器已经发展,包括了来自动态和函数式语言的许…

Vue关闭eslintrc校验

Vue关闭eslintrc校验vue.config.js文件添加 lintOnSave: falseeslintrc.js文件① 注释掉 @vue/standard ② 添加 ‘vue/multi-word-component-names’: ‘off’